adapt to proxi-finalize
This commit is contained in:
parent
ed791a47c5
commit
d76ed654d9
|
@ -0,0 +1,675 @@
|
|||
[
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "provider",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "proxy_admin",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleInfo",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleWhitelist",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleStartAndEndTimes",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_calldata",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "exec",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "registry_exec_id",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleStatus",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "decreaseApproval",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAdmin",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_storage",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [],
|
||||
"name": "buy",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"name": "init",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "isCrowdsaleFull",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "increaseApproval",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_exec_id",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_buyer",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getWhitelistStatus",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_index",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_version",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getTokensSold",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_storage",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_registry_exec_id",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "_provider",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_app_name",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "fallback"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "execution_id",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "message",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "StorageException",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,376 @@
|
|||
pragma solidity ^0.4.23;
|
||||
|
||||
// File: contracts/classes/admin/IAdmin.sol
|
||||
|
||||
interface IAdmin {
|
||||
function getAdmin() external view returns (address);
|
||||
function getCrowdsaleInfo() external view returns (uint, address, uint, bool, bool, bool);
|
||||
function isCrowdsaleFull() external view returns (bool, uint);
|
||||
function getCrowdsaleStartAndEndTimes() external view returns (uint, uint);
|
||||
function getCrowdsaleStatus() external view returns (uint, uint, uint, uint, uint, uint, bool);
|
||||
function getTokensSold() external view returns (uint);
|
||||
function getCrowdsaleWhitelist() external view returns (uint, address[]);
|
||||
function getWhitelistStatus(address) external view returns (uint, uint);
|
||||
}
|
||||
|
||||
interface AdminIdx {
|
||||
function getAdmin(address, bytes32) external view returns (address);
|
||||
function getCrowdsaleInfo(address, bytes32) external view returns (uint, address, uint, bool, bool, bool);
|
||||
function isCrowdsaleFull(address, bytes32) external view returns (bool, uint);
|
||||
function getCrowdsaleStartAndEndTimes(address, bytes32) external view returns (uint, uint);
|
||||
function getCrowdsaleStatus(address, bytes32) external view returns (uint, uint, uint, uint, uint, uint, bool);
|
||||
function getTokensSold(address, bytes32) external view returns (uint);
|
||||
function getCrowdsaleWhitelist(address, bytes32) external view returns (uint, address[]);
|
||||
function getWhitelistStatus(address, bytes32, address) external view returns (uint, uint);
|
||||
}
|
||||
|
||||
// File: contracts/classes/sale/ISale.sol
|
||||
|
||||
interface ISale {
|
||||
function buy() external payable;
|
||||
}
|
||||
|
||||
// File: contracts/classes/token/IToken.sol
|
||||
|
||||
interface IToken {
|
||||
function name() external view returns (string);
|
||||
function symbol() external view returns (string);
|
||||
function decimals() external view returns (uint8);
|
||||
function totalSupply() external view returns (uint);
|
||||
function balanceOf(address) external view returns (uint);
|
||||
function allowance(address, address) external view returns (uint);
|
||||
function transfer(address, uint) external returns (bool);
|
||||
function transferFrom(address, address, uint) external returns (bool);
|
||||
function approve(address, uint) external returns (bool);
|
||||
function increaseApproval(address, uint) external returns (bool);
|
||||
function decreaseApproval(address, uint) external returns (bool);
|
||||
event Transfer(address indexed from, address indexed to, uint amt);
|
||||
event Approval(address indexed owner, address indexed spender, uint amt);
|
||||
}
|
||||
|
||||
interface TokenIdx {
|
||||
function name(address, bytes32) external view returns (bytes32);
|
||||
function symbol(address, bytes32) external view returns (bytes32);
|
||||
function decimals(address, bytes32) external view returns (uint8);
|
||||
function totalSupply(address, bytes32) external view returns (uint);
|
||||
function balanceOf(address, bytes32, address) external view returns (uint);
|
||||
function allowance(address, bytes32, address, address) external view returns (uint);
|
||||
}
|
||||
|
||||
// File: contracts/IDutchCrowdsale.sol
|
||||
|
||||
interface IDutchCrowdsale {
|
||||
function init(address, uint, uint, uint, uint, uint, uint, bool, address, bool) external;
|
||||
}
|
||||
|
||||
// File: authos-solidity/contracts/interfaces/StorageInterface.sol
|
||||
|
||||
interface StorageInterface {
|
||||
function getTarget(bytes32 exec_id, bytes4 selector)
|
||||
external view returns (address implementation);
|
||||
function getIndex(bytes32 exec_id) external view returns (address index);
|
||||
function createInstance(address sender, bytes32 app_name, address provider, bytes32 registry_exec_id, bytes calldata)
|
||||
external payable returns (bytes32 instance_exec_id, bytes32 version);
|
||||
function createRegistry(address index, address implementation) external returns (bytes32 exec_id);
|
||||
function exec(address sender, bytes32 exec_id, bytes calldata)
|
||||
external payable returns (uint emitted, uint paid, uint stored);
|
||||
}
|
||||
|
||||
// File: authos-solidity/contracts/core/Proxy.sol
|
||||
|
||||
contract Proxy {
|
||||
|
||||
// Registry storage
|
||||
address public proxy_admin;
|
||||
StorageInterface public app_storage;
|
||||
bytes32 public registry_exec_id;
|
||||
address public provider;
|
||||
bytes32 public app_name;
|
||||
|
||||
// App storage
|
||||
bytes32 public app_version;
|
||||
bytes32 public app_exec_id;
|
||||
address public app_index;
|
||||
|
||||
// Function selector for storage 'exec' function
|
||||
bytes4 internal constant EXEC_SEL = bytes4(keccak256('exec(address,bytes32,bytes)'));
|
||||
|
||||
// Event emitted in case of a revert from storage
|
||||
event StorageException(bytes32 indexed execution_id, string message);
|
||||
|
||||
// For storage refunds
|
||||
function () external payable { }
|
||||
|
||||
// Constructor - sets proxy admin, as well as initial variables
|
||||
constructor (address _storage, bytes32 _registry_exec_id, address _provider, bytes32 _app_name) public {
|
||||
proxy_admin = msg.sender;
|
||||
app_storage = StorageInterface(_storage);
|
||||
registry_exec_id = _registry_exec_id;
|
||||
provider = _provider;
|
||||
app_name = _app_name;
|
||||
}
|
||||
|
||||
// Declare abstract execution function -
|
||||
function exec(bytes _calldata) external payable returns (bool);
|
||||
|
||||
// Checks to see if an error message was returned with the failed call, and emits it if so -
|
||||
function checkErrors() internal {
|
||||
// If the returned data begins with selector 'Error(string)', get the contained message -
|
||||
string memory message;
|
||||
bytes4 err_sel = bytes4(keccak256('Error(string)'));
|
||||
assembly {
|
||||
// Get pointer to free memory, place returned data at pointer, and update free memory pointer
|
||||
let ptr := mload(0x40)
|
||||
returndatacopy(ptr, 0, returndatasize)
|
||||
mstore(0x40, add(ptr, returndatasize))
|
||||
|
||||
// Check value at pointer for equality with Error selector -
|
||||
if eq(mload(ptr), and(err_sel, 0xffffffff00000000000000000000000000000000000000000000000000000000)) {
|
||||
message := add(0x24, ptr)
|
||||
}
|
||||
}
|
||||
// If no returned message exists, emit a default error message. Otherwise, emit the error message
|
||||
if (bytes(message).length == 0)
|
||||
emit StorageException(app_exec_id, "No error recieved");
|
||||
else
|
||||
emit StorageException(app_exec_id, message);
|
||||
}
|
||||
}
|
||||
|
||||
// File: authos-solidity/contracts/lib/StringUtils.sol
|
||||
|
||||
library StringUtils {
|
||||
|
||||
function toStr(bytes32 _val) internal pure returns (string memory str) {
|
||||
assembly {
|
||||
str := mload(0x40)
|
||||
mstore(str, 0x20)
|
||||
mstore(add(0x20, str), _val)
|
||||
mstore(0x40, add(0x40, str))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// File: contracts/DutchProxy.sol
|
||||
|
||||
contract SaleProxy is ISale, Proxy {
|
||||
|
||||
// Allows a sender to purchase tokens from the active sale
|
||||
function buy() external payable {
|
||||
if (address(app_storage).call.value(msg.value)(abi.encodeWithSelector(
|
||||
EXEC_SEL, msg.sender, app_exec_id, msg.data
|
||||
)) == false) checkErrors(); // Call failed - emit errors
|
||||
// Return unspent wei to sender
|
||||
address(msg.sender).transfer(address(this).balance);
|
||||
}
|
||||
}
|
||||
|
||||
contract AdminProxy is IAdmin, SaleProxy {
|
||||
|
||||
/*
|
||||
Returns the admin address for the crowdsale
|
||||
|
||||
@return address: The admin of the crowdsale
|
||||
*/
|
||||
function getAdmin() external view returns (address) {
|
||||
return AdminIdx(app_index).getAdmin(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns information about the ongoing sale -
|
||||
|
||||
@return uint: The total number of wei raised during the sale
|
||||
@return address: The team funds wallet
|
||||
@return uint: The minimum number of tokens a purchaser must buy
|
||||
@return bool: Whether the sale is finished configuring
|
||||
@return bool: Whether the sale has completed
|
||||
@return bool: Whether the unsold tokens at the end of the sale are burnt (if false, they are sent to the team wallet)
|
||||
*/
|
||||
function getCrowdsaleInfo() external view returns (uint, address, uint, bool, bool, bool) {
|
||||
return AdminIdx(app_index).getCrowdsaleInfo(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns whether or not the sale is full, as well as the maximum number of sellable tokens
|
||||
If the current rate is such that no more tokens can be purchased, returns true
|
||||
|
||||
@return bool: Whether or not the sale is sold out
|
||||
@return uint: The total number of tokens for sale
|
||||
*/
|
||||
function isCrowdsaleFull() external view returns (bool, uint) {
|
||||
return AdminIdx(app_index).isCrowdsaleFull(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the start and end times of the sale
|
||||
|
||||
@return uint: The time at which the sale will begin
|
||||
@return uint: The time at which the sale will end
|
||||
*/
|
||||
function getCrowdsaleStartAndEndTimes() external view returns (uint, uint) {
|
||||
return AdminIdx(app_index).getCrowdsaleStartAndEndTimes(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns information about the current sale tier
|
||||
|
||||
@return uint: The price of 1 token (10^decimals) in wei at the start of the sale
|
||||
@return uint: The price of 1 token (10^decimals) in wei at the end of the sale
|
||||
@return uint: The price of 1 token (10^decimals) currently
|
||||
@return uint: The total duration of the sale
|
||||
@return uint: The amount of time remaining in the sale (factors in time till sale starts)
|
||||
@return uint: The amount of tokens still available to be sold
|
||||
@return bool: Whether the sale is whitelisted or not
|
||||
*/
|
||||
function getCrowdsaleStatus() external view returns (uint, uint, uint, uint, uint, uint, bool) {
|
||||
return AdminIdx(app_index).getCrowdsaleStatus(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the number of tokens sold during the sale, so far
|
||||
|
||||
@return uint: The number of tokens sold during the sale up to this point
|
||||
*/
|
||||
function getTokensSold() external view returns (uint) {
|
||||
return AdminIdx(app_index).getTokensSold(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the whitelist set by the admin
|
||||
|
||||
@return uint: The length of the whitelist
|
||||
@return address[]: The list of addresses in the whitelist
|
||||
*/
|
||||
function getCrowdsaleWhitelist() external view returns (uint, address[]) {
|
||||
return AdminIdx(app_index).getCrowdsaleWhitelist(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns whitelist information for a buyer
|
||||
|
||||
@param _buyer: The address about which the whitelist information will be retrieved
|
||||
@return uint: The minimum number of tokens the buyer must make during the sale
|
||||
@return uint: The maximum amount of tokens allowed to be purchased by the buyer
|
||||
*/
|
||||
function getWhitelistStatus(address _buyer) external view returns (uint, uint) {
|
||||
return AdminIdx(app_index).getWhitelistStatus(app_storage, app_exec_id, _buyer);
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenProxy is IToken, AdminProxy {
|
||||
|
||||
using StringUtils for bytes32;
|
||||
|
||||
// Returns the name of the token
|
||||
function name() external view returns (string) {
|
||||
return TokenIdx(app_index).name(app_storage, app_exec_id).toStr();
|
||||
}
|
||||
|
||||
// Returns the symbol of the token
|
||||
function symbol() external view returns (string) {
|
||||
return TokenIdx(app_index).symbol(app_storage, app_exec_id).toStr();
|
||||
}
|
||||
|
||||
// Returns the number of decimals the token has
|
||||
function decimals() external view returns (uint8) {
|
||||
return TokenIdx(app_index).decimals(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
// Returns the total supply of the token
|
||||
function totalSupply() external view returns (uint) {
|
||||
return TokenIdx(app_index).totalSupply(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
// Returns the token balance of the owner
|
||||
function balanceOf(address _owner) external view returns (uint) {
|
||||
return TokenIdx(app_index).balanceOf(app_storage, app_exec_id, _owner);
|
||||
}
|
||||
|
||||
// Returns the number of tokens allowed by the owner to be spent by the spender
|
||||
function allowance(address _owner, address _spender) external view returns (uint) {
|
||||
return TokenIdx(app_index).allowance(app_storage, app_exec_id, _owner, _spender);
|
||||
}
|
||||
|
||||
// Executes a transfer, sending tokens to the recipient
|
||||
function transfer(address _to, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Transfer(msg.sender, _to, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Executes a transferFrom, transferring tokens from the _from account by using an allowed amount
|
||||
function transferFrom(address _from, address _to, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Transfer(_from, _to, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Approve a spender for a given amount
|
||||
function approve(address _spender, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Approval(msg.sender, _spender, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Increase the amount approved for the spender
|
||||
function increaseApproval(address _spender, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Approval(msg.sender, _spender, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decrease the amount approved for the spender, to a minimum of 0
|
||||
function decreaseApproval(address _spender, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Approval(msg.sender, _spender, _amt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
contract DutchProxy is IDutchCrowdsale, TokenProxy {
|
||||
|
||||
// Constructor - sets storage address, registry id, provider, and app name
|
||||
constructor (address _storage, bytes32 _registry_exec_id, address _provider, bytes32 _app_name) public
|
||||
Proxy(_storage, _registry_exec_id, _provider, _app_name) { }
|
||||
|
||||
// Constructor - creates a new instance of the application in storage, and sets this proxy's exec id
|
||||
function init(address, uint, uint, uint, uint, uint, uint, bool, address, bool) external {
|
||||
require(msg.sender == proxy_admin && app_exec_id == 0 && app_name != 0);
|
||||
(app_exec_id, app_version) = app_storage.createInstance(
|
||||
msg.sender, app_name, provider, registry_exec_id, msg.data
|
||||
);
|
||||
app_index = app_storage.getIndex(app_exec_id);
|
||||
}
|
||||
|
||||
// Executes an arbitrary function in this application
|
||||
function exec(bytes _calldata) external payable returns (bool success) {
|
||||
require(app_exec_id != 0 && _calldata.length >= 4);
|
||||
// Call 'exec' in AbstractStorage, passing in the sender's address, the app exec id, and the calldata to forward -
|
||||
app_storage.exec.value(msg.value)(msg.sender, app_exec_id, _calldata);
|
||||
|
||||
// Get returned data
|
||||
success = checkReturn();
|
||||
// If execution failed, emit errors -
|
||||
if (!success) checkErrors();
|
||||
|
||||
// Transfer any returned wei back to the sender
|
||||
msg.sender.transfer(address(this).balance);
|
||||
}
|
||||
|
||||
// Checks data returned by an application and returns whether or not the execution changed state
|
||||
function checkReturn() internal pure returns (bool success) {
|
||||
success = false;
|
||||
assembly {
|
||||
// returndata size must be 0x60 bytes
|
||||
if eq(returndatasize, 0x60) {
|
||||
// Copy returned data to pointer and check that at least one value is nonzero
|
||||
let ptr := mload(0x40)
|
||||
returndatacopy(ptr, 0, returndatasize)
|
||||
if iszero(iszero(mload(ptr))) { success := 1 }
|
||||
if iszero(iszero(mload(add(0x20, ptr)))) { success := 1 }
|
||||
if iszero(iszero(mload(add(0x40, ptr)))) { success := 1 }
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,841 @@
|
|||
[
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "provider",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleMaxRaise",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "proxy_admin",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleInfo",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_tier",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_buyer",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getWhitelistStatus",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleTierList",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleStartAndEndTimes",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_calldata",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "exec",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "registry_exec_id",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "decreaseApproval",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAdmin",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getReservedTokenDestinationList",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_storage",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_idx",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getTierStartAndEndDates",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [],
|
||||
"name": "buy",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_idx",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getCrowdsaleTier",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_destination",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getReservedDestinationInfo",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "isCrowdsaleFull",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "increaseApproval",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_exec_id",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_index",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "app_version",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getTokensSold",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCurrentTierInfo",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_tier_idx",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getTierWhitelist",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "init",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getCrowdsaleUniqueBuyers",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_storage",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_registry_exec_id",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "_provider",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_app_name",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "fallback"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "execution_id",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "message",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "StorageException",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amt",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,479 @@
|
|||
pragma solidity ^0.4.23;
|
||||
|
||||
// File: contracts/classes/sale/ISale.sol
|
||||
|
||||
interface ISale {
|
||||
function buy() external payable;
|
||||
}
|
||||
|
||||
// File: contracts/classes/sale_manager/ISaleManager.sol
|
||||
|
||||
interface ISaleManager {
|
||||
function getAdmin() external view returns (address);
|
||||
function getCrowdsaleInfo() external view returns (uint, address, bool, bool);
|
||||
function isCrowdsaleFull() external view returns (bool, uint);
|
||||
function getCrowdsaleStartAndEndTimes() external view returns (uint, uint);
|
||||
function getCurrentTierInfo() external view returns (bytes32, uint, uint, uint, uint, uint, bool, bool);
|
||||
function getCrowdsaleTier(uint) external view returns (bytes32, uint, uint, uint, uint, bool, bool);
|
||||
function getTierWhitelist(uint) external view returns (uint, address[]);
|
||||
function getCrowdsaleMaxRaise() external view returns (uint, uint);
|
||||
function getCrowdsaleTierList() external view returns (bytes32[]);
|
||||
function getCrowdsaleUniqueBuyers() external view returns (uint);
|
||||
function getTierStartAndEndDates(uint) external view returns (uint, uint);
|
||||
function getTokensSold() external view returns (uint);
|
||||
function getWhitelistStatus(uint, address) external view returns (uint, uint);
|
||||
}
|
||||
|
||||
interface SaleManagerIdx {
|
||||
function getAdmin(address, bytes32) external view returns (address);
|
||||
function getCrowdsaleInfo(address, bytes32) external view returns (uint, address, bool, bool);
|
||||
function isCrowdsaleFull(address, bytes32) external view returns (bool, uint);
|
||||
function getCrowdsaleStartAndEndTimes(address, bytes32) external view returns (uint, uint);
|
||||
function getCurrentTierInfo(address, bytes32) external view returns (bytes32, uint, uint, uint, uint, uint, bool, bool);
|
||||
function getCrowdsaleTier(address, bytes32, uint) external view returns (bytes32, uint, uint, uint, uint, bool, bool);
|
||||
function getTierWhitelist(address, bytes32, uint) external view returns (uint, address[]);
|
||||
function getCrowdsaleMaxRaise(address, bytes32) external view returns (uint, uint);
|
||||
function getCrowdsaleTierList(address, bytes32) external view returns (bytes32[]);
|
||||
function getCrowdsaleUniqueBuyers(address, bytes32) external view returns (uint);
|
||||
function getTierStartAndEndDates(address, bytes32, uint) external view returns (uint, uint);
|
||||
function getTokensSold(address, bytes32) external view returns (uint);
|
||||
function getWhitelistStatus(address, bytes32, uint, address) external view returns (uint, uint);
|
||||
}
|
||||
|
||||
// File: contracts/classes/token/IToken.sol
|
||||
|
||||
interface IToken {
|
||||
function name() external view returns (string);
|
||||
function symbol() external view returns (string);
|
||||
function decimals() external view returns (uint8);
|
||||
function totalSupply() external view returns (uint);
|
||||
function balanceOf(address) external view returns (uint);
|
||||
function allowance(address, address) external view returns (uint);
|
||||
function transfer(address, uint) external returns (bool);
|
||||
function transferFrom(address, address, uint) external returns (bool);
|
||||
function approve(address, uint) external returns (bool);
|
||||
function increaseApproval(address, uint) external returns (bool);
|
||||
function decreaseApproval(address, uint) external returns (bool);
|
||||
event Transfer(address indexed from, address indexed to, uint amt);
|
||||
event Approval(address indexed owner, address indexed spender, uint amt);
|
||||
}
|
||||
|
||||
interface TokenIdx {
|
||||
function name(address, bytes32) external view returns (bytes32);
|
||||
function symbol(address, bytes32) external view returns (bytes32);
|
||||
function decimals(address, bytes32) external view returns (uint8);
|
||||
function totalSupply(address, bytes32) external view returns (uint);
|
||||
function balanceOf(address, bytes32, address) external view returns (uint);
|
||||
function allowance(address, bytes32, address, address) external view returns (uint);
|
||||
}
|
||||
|
||||
// File: contracts/classes/token_manager/ITokenManager.sol
|
||||
|
||||
interface ITokenManager {
|
||||
function getReservedTokenDestinationList() external view returns (uint, address[]);
|
||||
function getReservedDestinationInfo(address) external view returns (uint, uint, uint, uint);
|
||||
}
|
||||
|
||||
interface TokenManagerIdx {
|
||||
function getReservedTokenDestinationList(address, bytes32) external view returns (uint, address[]);
|
||||
function getReservedDestinationInfo(address, bytes32, address) external view returns (uint, uint, uint, uint);
|
||||
}
|
||||
|
||||
// File: contracts/IMintedCapped.sol
|
||||
|
||||
interface IMintedCapped {
|
||||
function init(address, uint, bytes32, uint, uint, uint, uint, bool, bool, address) external;
|
||||
}
|
||||
|
||||
// File: authos-solidity/contracts/interfaces/StorageInterface.sol
|
||||
|
||||
interface StorageInterface {
|
||||
function getTarget(bytes32 exec_id, bytes4 selector)
|
||||
external view returns (address implementation);
|
||||
function getIndex(bytes32 exec_id) external view returns (address index);
|
||||
function createInstance(address sender, bytes32 app_name, address provider, bytes32 registry_exec_id, bytes calldata)
|
||||
external payable returns (bytes32 instance_exec_id, bytes32 version);
|
||||
function createRegistry(address index, address implementation) external returns (bytes32 exec_id);
|
||||
function exec(address sender, bytes32 exec_id, bytes calldata)
|
||||
external payable returns (uint emitted, uint paid, uint stored);
|
||||
}
|
||||
|
||||
// File: authos-solidity/contracts/core/Proxy.sol
|
||||
|
||||
contract Proxy {
|
||||
|
||||
// Registry storage
|
||||
address public proxy_admin;
|
||||
StorageInterface public app_storage;
|
||||
bytes32 public registry_exec_id;
|
||||
address public provider;
|
||||
bytes32 public app_name;
|
||||
|
||||
// App storage
|
||||
bytes32 public app_version;
|
||||
bytes32 public app_exec_id;
|
||||
address public app_index;
|
||||
|
||||
// Function selector for storage 'exec' function
|
||||
bytes4 internal constant EXEC_SEL = bytes4(keccak256('exec(address,bytes32,bytes)'));
|
||||
|
||||
// Event emitted in case of a revert from storage
|
||||
event StorageException(bytes32 indexed execution_id, string message);
|
||||
|
||||
// For storage refunds
|
||||
function () external payable { }
|
||||
|
||||
// Constructor - sets proxy admin, as well as initial variables
|
||||
constructor (address _storage, bytes32 _registry_exec_id, address _provider, bytes32 _app_name) public {
|
||||
proxy_admin = msg.sender;
|
||||
app_storage = StorageInterface(_storage);
|
||||
registry_exec_id = _registry_exec_id;
|
||||
provider = _provider;
|
||||
app_name = _app_name;
|
||||
}
|
||||
|
||||
// Declare abstract execution function -
|
||||
function exec(bytes _calldata) external payable returns (bool);
|
||||
|
||||
// Checks to see if an error message was returned with the failed call, and emits it if so -
|
||||
function checkErrors() internal {
|
||||
// If the returned data begins with selector 'Error(string)', get the contained message -
|
||||
string memory message;
|
||||
bytes4 err_sel = bytes4(keccak256('Error(string)'));
|
||||
assembly {
|
||||
// Get pointer to free memory, place returned data at pointer, and update free memory pointer
|
||||
let ptr := mload(0x40)
|
||||
returndatacopy(ptr, 0, returndatasize)
|
||||
mstore(0x40, add(ptr, returndatasize))
|
||||
|
||||
// Check value at pointer for equality with Error selector -
|
||||
if eq(mload(ptr), and(err_sel, 0xffffffff00000000000000000000000000000000000000000000000000000000)) {
|
||||
message := add(0x24, ptr)
|
||||
}
|
||||
}
|
||||
// If no returned message exists, emit a default error message. Otherwise, emit the error message
|
||||
if (bytes(message).length == 0)
|
||||
emit StorageException(app_exec_id, "No error recieved");
|
||||
else
|
||||
emit StorageException(app_exec_id, message);
|
||||
}
|
||||
}
|
||||
|
||||
// File: authos-solidity/contracts/lib/StringUtils.sol
|
||||
|
||||
library StringUtils {
|
||||
|
||||
function toStr(bytes32 _val) internal pure returns (string memory str) {
|
||||
assembly {
|
||||
str := mload(0x40)
|
||||
mstore(str, 0x20)
|
||||
mstore(add(0x20, str), _val)
|
||||
mstore(0x40, add(0x40, str))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// File: contracts/MintedCappedProxy.sol
|
||||
|
||||
contract SaleProxy is ISale, Proxy {
|
||||
|
||||
// Allows a sender to purchase tokens from the active sale
|
||||
function buy() external payable {
|
||||
if (address(app_storage).call.value(msg.value)(abi.encodeWithSelector(
|
||||
EXEC_SEL, msg.sender, app_exec_id, msg.data
|
||||
)) == false) checkErrors(); // Call failed - emit errors
|
||||
// Return unspent wei to sender
|
||||
address(msg.sender).transfer(address(this).balance);
|
||||
}
|
||||
}
|
||||
|
||||
contract SaleManagerProxy is ISaleManager, SaleProxy {
|
||||
|
||||
/*
|
||||
Returns the admin address for the crowdsale
|
||||
|
||||
@return address: The admin of the crowdsale
|
||||
*/
|
||||
function getAdmin() external view returns (address) {
|
||||
return SaleManagerIdx(app_index).getAdmin(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns information about the ongoing sale -
|
||||
|
||||
@return uint: The total number of wei raised during the sale
|
||||
@return address: The team funds wallet
|
||||
@return bool: Whether the sale is finished configuring
|
||||
@return bool: Whether the sale has completed
|
||||
*/
|
||||
function getCrowdsaleInfo() external view returns (uint, address, bool, bool) {
|
||||
return SaleManagerIdx(app_index).getCrowdsaleInfo(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns whether or not the sale is full, as well as the maximum number of sellable tokens
|
||||
|
||||
@return bool: Whether or not the sale is sold out
|
||||
@return uint: The total number of tokens for sale
|
||||
*/
|
||||
function isCrowdsaleFull() external view returns (bool, uint) {
|
||||
return SaleManagerIdx(app_index).isCrowdsaleFull(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the start and end times of the sale
|
||||
|
||||
@return uint: The time at which the sale will begin
|
||||
@return uint: The time at which the sale will end
|
||||
*/
|
||||
function getCrowdsaleStartAndEndTimes() external view returns (uint, uint) {
|
||||
return SaleManagerIdx(app_index).getCrowdsaleStartAndEndTimes(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns information about the current sale tier
|
||||
|
||||
@return bytes32: The tier's name
|
||||
@return uint: The index of the tier
|
||||
@return uint: The time at which the tier will end
|
||||
@return uint: The number of tokens remaining for sale during this tier
|
||||
@return uint: The price of 1 token (10^decimals units) in wei
|
||||
@return uint: The minimum amount of tokens that must be purchased during this tier
|
||||
@return bool: Whether the tier's duration can be modified by the sale admin, prior to it beginning
|
||||
@return bool: Whether the tier is whitelisted
|
||||
*/
|
||||
function getCurrentTierInfo() external view returns (bytes32, uint, uint, uint, uint, uint, bool, bool) {
|
||||
return SaleManagerIdx(app_index).getCurrentTierInfo(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns information about the tier represented by the given index
|
||||
|
||||
@param _idx: The index of the tier about which information will be returned
|
||||
@return bytes32: The tier's name
|
||||
@return uint: The number of tokens available for sale during this tier, in total
|
||||
@return uint: The price of 1 token (10^decimals units) in wei
|
||||
@return uint: The duration the tier lasts
|
||||
@return uint: The minimum amount of tokens that must be purchased during this tier
|
||||
@return bool: Whether the tier's duration can be modified by the sale admin, prior to it beginning
|
||||
@return bool: Whether the tier is whitelisted
|
||||
*/
|
||||
function getCrowdsaleTier(uint _idx) external view returns (bytes32, uint, uint, uint, uint, bool, bool) {
|
||||
return SaleManagerIdx(app_index).getCrowdsaleTier(app_storage, app_exec_id, _idx);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the whitelist associated with the given tier
|
||||
|
||||
@param _tier_idx: The index of the tier about which information will be returned
|
||||
@return uint: The length of the whitelist
|
||||
@return address[]: The list of addresses whitelisted
|
||||
*/
|
||||
function getTierWhitelist(uint _tier_idx) external view returns (uint, address[]) {
|
||||
return SaleManagerIdx(app_index).getTierWhitelist(app_storage, app_exec_id, _tier_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the maximum amount of wei that can be raised, as well as the total number of tokens that can be sold
|
||||
|
||||
@return uint: The maximum amount of wei that can be raised
|
||||
@return uint: The total number of tokens that can be sold
|
||||
*/
|
||||
function getCrowdsaleMaxRaise() external view returns (uint, uint) {
|
||||
return SaleManagerIdx(app_index).getCrowdsaleMaxRaise(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a list of the sale's tier names
|
||||
|
||||
@return bytes32[]: A list of the names of each of the tiers of the sale (names may not be unique)
|
||||
*/
|
||||
function getCrowdsaleTierList() external view returns (bytes32[]) {
|
||||
return SaleManagerIdx(app_index).getCrowdsaleTierList(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the number of unique contributors to the sale
|
||||
|
||||
@return uint: The number of unique contributors to the sale
|
||||
*/
|
||||
function getCrowdsaleUniqueBuyers() external view returns (uint) {
|
||||
return SaleManagerIdx(app_index).getCrowdsaleUniqueBuyers(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the start and end time of the given tier
|
||||
|
||||
@param _idx: The index of the tier about which information will be returned
|
||||
@return uint: The time at which the tier will begin
|
||||
@return uint: The time at which the tier will end
|
||||
*/
|
||||
function getTierStartAndEndDates(uint _idx) external view returns (uint, uint) {
|
||||
return SaleManagerIdx(app_index).getTierStartAndEndDates(app_storage, app_exec_id, _idx);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the total number of tokens sold during the sale
|
||||
|
||||
@return uint: The total number of tokens sold during the sale
|
||||
*/
|
||||
function getTokensSold() external view returns (uint) {
|
||||
return SaleManagerIdx(app_index).getTokensSold(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns whitelist information for a buyer during a given tier
|
||||
|
||||
@param _tier: The index of the tier whose whitelist will be queried
|
||||
@param _buyer: The address about which the whitelist information will be retrieved
|
||||
@return uint: The minimum number of tokens the buyer must make during the sale
|
||||
@return uint: The maximum amount of tokens able to be purchased by the buyer this tier
|
||||
*/
|
||||
function getWhitelistStatus(uint _tier, address _buyer) external view returns (uint, uint) {
|
||||
return SaleManagerIdx(app_index).getWhitelistStatus(app_storage, app_exec_id, _tier, _buyer);
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenManagerProxy is ITokenManager, SaleManagerProxy {
|
||||
|
||||
/*
|
||||
Returns the list of addresses for which tokens have been reserved
|
||||
|
||||
@return uint: The length of the list
|
||||
@return address[]: The list of destinations
|
||||
*/
|
||||
function getReservedTokenDestinationList() external view returns (uint, address[]) {
|
||||
return TokenManagerIdx(app_index).getReservedTokenDestinationList(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns information about a reserved token destination
|
||||
|
||||
@param _destination: The address whose reservation information will be queried
|
||||
@return uint: The index of the address in the reservation list
|
||||
@return uint: The number of tokens that will be minted for the destination when the sale is completed
|
||||
@return uint: The percent of tokens sold that will be minted for the destination when the sale is completed
|
||||
@return uint: The number of decimals in the above percent figure
|
||||
*/
|
||||
function getReservedDestinationInfo(address _destination) external view returns (uint, uint, uint, uint) {
|
||||
return TokenManagerIdx(app_index).getReservedDestinationInfo(app_storage, app_exec_id, _destination);
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenProxy is IToken, TokenManagerProxy {
|
||||
|
||||
using StringUtils for bytes32;
|
||||
|
||||
// Returns the name of the token
|
||||
function name() external view returns (string) {
|
||||
return TokenIdx(app_index).name(app_storage, app_exec_id).toStr();
|
||||
}
|
||||
|
||||
// Returns the symbol of the token
|
||||
function symbol() external view returns (string) {
|
||||
return TokenIdx(app_index).symbol(app_storage, app_exec_id).toStr();
|
||||
}
|
||||
|
||||
// Returns the number of decimals the token has
|
||||
function decimals() external view returns (uint8) {
|
||||
return TokenIdx(app_index).decimals(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
// Returns the total supply of the token
|
||||
function totalSupply() external view returns (uint) {
|
||||
return TokenIdx(app_index).totalSupply(app_storage, app_exec_id);
|
||||
}
|
||||
|
||||
// Returns the token balance of the owner
|
||||
function balanceOf(address _owner) external view returns (uint) {
|
||||
return TokenIdx(app_index).balanceOf(app_storage, app_exec_id, _owner);
|
||||
}
|
||||
|
||||
// Returns the number of tokens allowed by the owner to be spent by the spender
|
||||
function allowance(address _owner, address _spender) external view returns (uint) {
|
||||
return TokenIdx(app_index).allowance(app_storage, app_exec_id, _owner, _spender);
|
||||
}
|
||||
|
||||
// Executes a transfer, sending tokens to the recipient
|
||||
function transfer(address _to, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Transfer(msg.sender, _to, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Executes a transferFrom, transferring tokens from the _from account by using an allowed amount
|
||||
function transferFrom(address _from, address _to, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Transfer(_from, _to, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Approve a spender for a given amount
|
||||
function approve(address _spender, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Approval(msg.sender, _spender, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Increase the amount approved for the spender
|
||||
function increaseApproval(address _spender, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Approval(msg.sender, _spender, _amt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decrease the amount approved for the spender, to a minimum of 0
|
||||
function decreaseApproval(address _spender, uint _amt) external returns (bool) {
|
||||
app_storage.exec(msg.sender, app_exec_id, msg.data);
|
||||
emit Approval(msg.sender, _spender, _amt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
contract MintedCappedProxy is IMintedCapped, TokenProxy {
|
||||
|
||||
// Constructor - sets storage address, registry id, provider, and app name
|
||||
constructor (address _storage, bytes32 _registry_exec_id, address _provider, bytes32 _app_name) public
|
||||
Proxy(_storage, _registry_exec_id, _provider, _app_name) { }
|
||||
|
||||
// Constructor - creates a new instance of the application in storage, and sets this proxy's exec id
|
||||
function init(address, uint, bytes32, uint, uint, uint, uint, bool, bool, address) external {
|
||||
require(msg.sender == proxy_admin && app_exec_id == 0 && app_name != 0);
|
||||
(app_exec_id, app_version) = app_storage.createInstance(
|
||||
msg.sender, app_name, provider, registry_exec_id, msg.data
|
||||
);
|
||||
app_index = app_storage.getIndex(app_exec_id);
|
||||
}
|
||||
|
||||
// Executes an arbitrary function in this application
|
||||
function exec(bytes _calldata) external payable returns (bool success) {
|
||||
require(app_exec_id != 0 && _calldata.length >= 4);
|
||||
// Call 'exec' in AbstractStorage, passing in the sender's address, the app exec id, and the calldata to forward -
|
||||
app_storage.exec.value(msg.value)(msg.sender, app_exec_id, _calldata);
|
||||
|
||||
// Get returned data
|
||||
success = checkReturn();
|
||||
// If execution failed, emit errors -
|
||||
if (!success) checkErrors();
|
||||
|
||||
// Transfer any returned wei back to the sender
|
||||
msg.sender.transfer(address(this).balance);
|
||||
}
|
||||
|
||||
// Checks data returned by an application and returns whether or not the execution changed state
|
||||
function checkReturn() internal pure returns (bool success) {
|
||||
success = false;
|
||||
assembly {
|
||||
// returndata size must be 0x60 bytes
|
||||
if eq(returndatasize, 0x60) {
|
||||
// Copy returned data to pointer and check that at least one value is nonzero
|
||||
let ptr := mload(0x40)
|
||||
returndatacopy(ptr, 0, returndatasize)
|
||||
if iszero(iszero(mload(ptr))) { success := 1 }
|
||||
if iszero(iszero(mload(add(0x20, ptr)))) { success := 1 }
|
||||
if iszero(iszero(mload(add(0x40, ptr)))) { success := 1 }
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
[{"constant":true,"inputs":[],"name":"abstractStorageAddr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"deployer","type":"address"}],"name":"getCrowdsalesForUser","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"deployer","type":"address"}],"name":"countCrowdsalesForUser","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"proxyAddress","type":"address"}],"name":"getADminFromDutchProxy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newMintedCappedIdxAddr","type":"address"}],"name":"changeMintedCappedIdx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"proxyAddress","type":"address"}],"name":"getProxyExecID","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newDutchIdxAddr","type":"address"}],"name":"changeDutchIdxAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dutchIdxAddr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"proxyAddress","type":"address"}],"name":"getAdminFromMintedCappedProxy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mintedCappedIdxAddr","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAbstractStorageAddr","type":"address"}],"name":"changeAbstractStorage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"proxyAddress","type":"address"}],"name":"trackCrowdsale","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_abstractStorage","type":"address"},{"name":"_mintedCappedIdx","type":"address"},{"name":"_dutchIdx","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":true,"name":"proxyAddress","type":"address"},{"indexed":false,"name":"appExecID","type":"bytes32"}],"name":"Added","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,145 @@
|
|||
pragma solidity ^0.4.24;
|
||||
|
||||
/**
|
||||
* @title Ownable
|
||||
* @dev The Ownable contract has an owner address, and provides basic authorization control
|
||||
* functions, this simplifies the implementation of "user permissions".
|
||||
*/
|
||||
contract Ownable {
|
||||
address public owner;
|
||||
|
||||
|
||||
event OwnershipRenounced(address indexed previousOwner);
|
||||
event OwnershipTransferred(
|
||||
address indexed previousOwner,
|
||||
address indexed newOwner
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
|
||||
* account.
|
||||
*/
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Throws if called by any account other than the owner.
|
||||
*/
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the current owner to relinquish control of the contract.
|
||||
* @notice Renouncing to ownership will leave the contract without an owner.
|
||||
* It will not be possible to call the functions with the `onlyOwner`
|
||||
* modifier anymore.
|
||||
*/
|
||||
function renounceOwnership() public onlyOwner {
|
||||
emit OwnershipRenounced(owner);
|
||||
owner = address(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the current owner to transfer control of the contract to a newOwner.
|
||||
* @param _newOwner The address to transfer ownership to.
|
||||
*/
|
||||
function transferOwnership(address _newOwner) public onlyOwner {
|
||||
_transferOwnership(_newOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers control of the contract to a newOwner.
|
||||
* @param _newOwner The address to transfer ownership to.
|
||||
*/
|
||||
function _transferOwnership(address _newOwner) internal {
|
||||
require(_newOwner != address(0));
|
||||
emit OwnershipTransferred(owner, _newOwner);
|
||||
owner = _newOwner;
|
||||
}
|
||||
}
|
||||
|
||||
contract AbstractProxy {
|
||||
bytes32 public app_exec_id;
|
||||
function getAdmin() external view returns (address);
|
||||
}
|
||||
|
||||
contract MintedCappedIdx {
|
||||
function getAdmin(address, bytes32) external view returns (address);
|
||||
}
|
||||
|
||||
contract DutchIdx {
|
||||
function getAdmin(address, bytes32) external view returns (address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registry of contracts deployed from Token Wizard 2.0.
|
||||
*/
|
||||
contract TokenWizardProxiesRegistry is Ownable {
|
||||
address public abstractStorageAddr;
|
||||
address public mintedCappedIdxAddr;
|
||||
address public dutchIdxAddr;
|
||||
mapping (address => Crowdsale[]) private deployedCrowdsalesByUser;
|
||||
event Added(address indexed sender, address indexed proxyAddress, bytes32 appExecID);
|
||||
struct Crowdsale {
|
||||
address proxyAddress;
|
||||
bytes32 execID;
|
||||
}
|
||||
|
||||
constructor (
|
||||
address _abstractStorage,
|
||||
address _mintedCappedIdx,
|
||||
address _dutchIdx
|
||||
) public {
|
||||
require(_abstractStorage != address(0));
|
||||
require(_mintedCappedIdx != address(0));
|
||||
require(_dutchIdx != address(0));
|
||||
require(_abstractStorage != _mintedCappedIdx && _abstractStorage != _dutchIdx && _mintedCappedIdx != _dutchIdx);
|
||||
abstractStorageAddr = _abstractStorage;
|
||||
mintedCappedIdxAddr = _mintedCappedIdx;
|
||||
dutchIdxAddr = _dutchIdx;
|
||||
}
|
||||
|
||||
function changeAbstractStorage(address newAbstractStorageAddr) public onlyOwner {
|
||||
abstractStorageAddr = newAbstractStorageAddr;
|
||||
}
|
||||
|
||||
function changeMintedCappedIdx(address newMintedCappedIdxAddr) public onlyOwner {
|
||||
mintedCappedIdxAddr = newMintedCappedIdxAddr;
|
||||
}
|
||||
|
||||
function changeDutchIdxAddr(address newDutchIdxAddr) public onlyOwner {
|
||||
dutchIdxAddr = newDutchIdxAddr;
|
||||
}
|
||||
|
||||
function trackCrowdsale(address proxyAddress) public {
|
||||
AbstractProxy proxy = AbstractProxy(proxyAddress);
|
||||
require(proxyAddress != address(0));
|
||||
require(msg.sender == proxy.getAdmin());
|
||||
bytes32 appExecID = proxy.app_exec_id();
|
||||
require(mintedCappedIdx.getAdmin(abstractStorageAddr, appExecID) != address(0) || dutchIdx.getAdmin(abstractStorageAddr, appExecID) != address(0));
|
||||
MintedCappedIdx mintedCappedIdx = MintedCappedIdx(mintedCappedIdxAddr);
|
||||
DutchIdx dutchIdx = DutchIdx(dutchIdxAddr);
|
||||
for (uint i = 0; i < deployedCrowdsalesByUser[msg.sender].length; i++) {
|
||||
require(deployedCrowdsalesByUser[msg.sender][i].proxyAddress != proxyAddress);
|
||||
require(deployedCrowdsalesByUser[msg.sender][i].execID != appExecID);
|
||||
}
|
||||
deployedCrowdsalesByUser[msg.sender].push(Crowdsale({proxyAddress: proxyAddress, execID: appExecID}));
|
||||
emit Added(msg.sender, proxyAddress, appExecID);
|
||||
}
|
||||
|
||||
function countCrowdsalesForUser(address deployer) public view returns (uint) {
|
||||
return deployedCrowdsalesByUser[deployer].length;
|
||||
}
|
||||
|
||||
function getCrowdsalesForUser(address deployer) public view returns (address[]) {
|
||||
address[] storage proxies;
|
||||
for (uint k = 0; k < deployedCrowdsalesByUser[deployer].length; k++) {
|
||||
proxies.push(deployedCrowdsalesByUser[deployer][k].proxyAddress);
|
||||
}
|
||||
return proxies;
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ class Crowdsale {
|
|||
this.reservedTokens = [];
|
||||
this.gasPrice;
|
||||
|
||||
|
||||
this.tiers = [];
|
||||
this.tokenAddress;
|
||||
this.contractAddress;
|
||||
|
@ -21,6 +20,7 @@ class Crowdsale {
|
|||
this.executionID;
|
||||
this.networkID;
|
||||
this.sort;
|
||||
this.proxyAddress;
|
||||
}
|
||||
|
||||
async parser(fileName) {
|
||||
|
|
|
@ -40,9 +40,9 @@ class User {
|
|||
logger.info("getTokenBalance");
|
||||
try {
|
||||
const web3 = await Utils.getWeb3Instance(crowdsale.networkID);
|
||||
let contractAddress = await Utils.getContractAddressInitCrowdsale(crowdsale);
|
||||
let contractAddress = await Utils.getContractAddressIdx(crowdsale);
|
||||
logger.info("contractAddress" + contractAddress);
|
||||
let addressRegistryStorage = await Utils.getEnvAddressAbstractStorage();
|
||||
let addressRegistryStorage = await Utils.getFromEnvAbstractStorageAddress();
|
||||
logger.info("addressRegistryStorage" + addressRegistryStorage);
|
||||
let abi = await Utils.getContractABIInitCrowdsale(crowdsale);
|
||||
let myContract = new web3.eth.Contract(abi, contractAddress);
|
||||
|
@ -82,7 +82,7 @@ class User {
|
|||
logger.info("Open manage page")
|
||||
const startURL = Utils.getStartURL();
|
||||
let mngPage = new ManagePage(this.driver);
|
||||
mngPage.URL = startURL + "manage/" + crowdsale.executionID;
|
||||
mngPage.URL = startURL + "manage/" + crowdsale.proxyAddress;
|
||||
return await mngPage.open()
|
||||
&& await mngPage.waitUntilLoaderGone()
|
||||
&& !await mngPage.isDisplayedButtonOK();
|
||||
|
@ -370,7 +370,8 @@ class User {
|
|||
await wizardStep4.waitUntilDisplayedButtonContinue() &&
|
||||
await wizardStep4.clickButtonContinue() &&
|
||||
await wizardStep4.waitUntilLoaderGone();
|
||||
crowdsale.executionID = await crowdsalePage.getExecutionID();
|
||||
crowdsale.proxyAddress = await crowdsalePage.getProxyAddress();
|
||||
|
||||
counter = 200;
|
||||
do {
|
||||
await this.driver.sleep(300);
|
||||
|
@ -388,10 +389,14 @@ class User {
|
|||
crowdsale.url = await investPage.getURL();
|
||||
|
||||
logger.info("Final invest page link: " + crowdsale.url);
|
||||
logger.info("token address: " + crowdsale.executionID);
|
||||
logger.info("proxyAddress " + crowdsale.proxyAddress);
|
||||
crowdsale.networkID = this.networkID;
|
||||
crowdsale.sort = 'minted';
|
||||
return result && crowdsale.executionID !== "";
|
||||
crowdsale.executionID = await Utils.getProxyExecID(crowdsale);
|
||||
logger.info("executionID " + crowdsale.executionID);
|
||||
|
||||
|
||||
return result && crowdsale.proxyAddress !== "";
|
||||
}
|
||||
|
||||
async createDutchAuctionCrowdsale(crowdsale) {
|
||||
|
@ -451,7 +456,7 @@ class User {
|
|||
await wizardStep4.clickButtonContinue() &&
|
||||
await wizardStep4.waitUntilLoaderGone();
|
||||
if (!result) return false;
|
||||
crowdsale.executionID = await crowdsalePage.getExecutionID();
|
||||
crowdsale.proxyAddress = await crowdsalePage.getProxyAddress();
|
||||
|
||||
counter = 200;
|
||||
do {
|
||||
|
@ -470,12 +475,14 @@ class User {
|
|||
crowdsale.url = await investPage.getURL();
|
||||
|
||||
logger.info("Final invest page link: " + crowdsale.url);
|
||||
logger.info("token address: " + crowdsale.executionID);
|
||||
logger.info("proxyAddress: " + crowdsale.proxyAddress);
|
||||
crowdsale.networkID = this.networkID;
|
||||
logger.info("crowdsale.networkID " + crowdsale.networkID);
|
||||
crowdsale.networkID = this.networkID;
|
||||
crowdsale.sort = 'dutch';
|
||||
return result && crowdsale.executionID !== "";
|
||||
crowdsale.executionID = await Utils.getProxyExecID(crowdsale);
|
||||
logger.info("executionID " + crowdsale.executionID);
|
||||
return result && crowdsale.proxyAddress !== "";
|
||||
}
|
||||
|
||||
async changeMinCapFromManagePage(tier, value) {
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
"margo": "node ./test/margo.js",
|
||||
"e2eMintedRopsten": "mocha ./test/e2eMintedRopsten.js",
|
||||
"e2eDutchRopsten": "mocha ./test/e2eDutchRopsten.js",
|
||||
"tr": "mocha -b ./test/funcDutchRateTime.js"
|
||||
"tr": "mocha -b ./test/funcDutchRateTime.js",
|
||||
"testDecimals":"mocha -b ./test/testDecimals.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"chromedriver": "^2.35.0",
|
||||
|
|
|
@ -22,8 +22,8 @@ class CrowdsalePage extends Page {
|
|||
return await super.clickWithWait(buttonInvest);
|
||||
}
|
||||
|
||||
async getExecutionID() {
|
||||
logger.info(this.name + "getExecutionID");
|
||||
async getProxyAddress() {
|
||||
logger.info(this.name + "getProxyAddress");
|
||||
return await super.getTextForElement(fieldExecID);
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ class MetaMask extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
async signTransaction(refreshCount,tier) {
|
||||
async signTransaction(refreshCount, tier) {
|
||||
logger.info(this.name + "signTransaction ");
|
||||
await this.switchToNextPage();
|
||||
let counter = 5;
|
||||
|
@ -121,8 +121,9 @@ class MetaMask extends Page {
|
|||
await super.waitUntilLocated(iconChangeAccount);
|
||||
if (await this.isElementDisplayed(buttonSubmit)) {
|
||||
|
||||
return await this.fillGasLimit( 6600000)
|
||||
&& await this.clickButtonSubmitTransaction()
|
||||
return await this.fillGasLimit(4600000)
|
||||
&& await this.waitUntilDisplayed(buttonSubmit)
|
||||
&& await this.clickButtonSubmitTransaction()
|
||||
&& await this.switchToNextPage();
|
||||
}
|
||||
await this.driver.sleep(3000);
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "DutchDecimalsWhitelist.json",
|
||||
"ticker": "test",
|
||||
"decimals": 0,
|
||||
"totalSupply":100,
|
||||
"walletAddress":"0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b",
|
||||
"gasprice":50,
|
||||
"burnExcess":false,
|
||||
"tiers":[
|
||||
{
|
||||
"isWhitelisted":true,
|
||||
"startDate": "180000",
|
||||
"startTime": "180000",
|
||||
"endDate":"72000000",
|
||||
"endTime":"72000000",
|
||||
"minCap":11,
|
||||
"minRate":1000,
|
||||
"maxRate":10000,
|
||||
"supply": 100,
|
||||
"whitelist":[{
|
||||
"address": "0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b",
|
||||
"min": 50,
|
||||
"max": 150
|
||||
} ]
|
||||
}]
|
||||
}
|
|
@ -1,25 +1,28 @@
|
|||
{
|
||||
|
||||
"name": "scenarioDutchRopsten.json",
|
||||
"ticker": "test",
|
||||
"decimals": 10,
|
||||
"totalSupply":100,
|
||||
"walletAddress":"0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b",
|
||||
"gasprice":300,
|
||||
|
||||
"gasprice":150,
|
||||
"burnExcess":false,
|
||||
"tiers":[
|
||||
{
|
||||
|
||||
"isWhitelisted":false,
|
||||
"startDate": "600000",
|
||||
"startTime": "600000",
|
||||
"endDate":"700000",
|
||||
"endTime":"700000",
|
||||
"isWhitelisted":true,
|
||||
"startDate": "240000",
|
||||
"startTime": "240000",
|
||||
"endDate":"360000",
|
||||
"endTime":"360000",
|
||||
"minCap":11,
|
||||
"minRate":1000,
|
||||
"maxRate":10000,
|
||||
"supply": 100,
|
||||
"whitelist":[
|
||||
{
|
||||
"address": "0xF16AB2EA0a7F7B28C267cbA3Ed211Ea5c6e27411",
|
||||
"min": 50,
|
||||
"max": 150
|
||||
}
|
||||
|
||||
]
|
||||
}]
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "MintedDecimalsWhitelist",
|
||||
"ticker": "test",
|
||||
"decimals": 0,
|
||||
"reservedTokens":[
|
||||
|
||||
],
|
||||
"walletAddress":"0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b",
|
||||
"gasprice": 1,
|
||||
|
||||
"tiers":[
|
||||
{
|
||||
"name":"###1",
|
||||
"allowModify": true,
|
||||
"isWhitelisted":true,
|
||||
"startDate": "120000",
|
||||
"startTime": "120000",
|
||||
"endDate":"23/02/2050",
|
||||
"endTime":"12:34",
|
||||
"minCap":11,
|
||||
"rate":200,
|
||||
"supply": 250,
|
||||
"whitelist":[
|
||||
{
|
||||
"address": "0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b",
|
||||
"min": 50,
|
||||
"max": 150
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
]
|
||||
}
|
|
@ -2,49 +2,41 @@
|
|||
|
||||
"name": "scenarioE2eMintedRopsten.json",
|
||||
"ticker": "test",
|
||||
"decimals": 18,
|
||||
"decimals": 10,
|
||||
"reservedTokens":[
|
||||
|
||||
],
|
||||
"walletAddress":"0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b",
|
||||
"gasprice":300,
|
||||
"gasprice":150,
|
||||
|
||||
"tiers":[
|
||||
{
|
||||
"name":"###1",
|
||||
"allowModify": true,
|
||||
"isWhitelisted":true,
|
||||
"isWhitelisted":false,
|
||||
"startDate": "600000",
|
||||
"startTime": "600000",
|
||||
"endDate":"800000",
|
||||
"endTime":"800000",
|
||||
"minCap":13,
|
||||
"rate":1000,
|
||||
"endDate":"720000",
|
||||
"endTime":"720000",
|
||||
"minCap":11,
|
||||
"rate":2000,
|
||||
"supply": 100,
|
||||
"whitelist":[{
|
||||
"address": "0xF16AB2EA0a7F7B28C267cbA3Ed211Ea5c6e27411",
|
||||
"min": 10,
|
||||
"max": 150
|
||||
}]
|
||||
"whitelist":[
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"###2",
|
||||
"allowModify": true,
|
||||
"isWhitelisted":true,
|
||||
"isWhitelisted":false,
|
||||
"startDate": "",
|
||||
"startTime": "",
|
||||
"endDate":"",
|
||||
"endTime":"",
|
||||
"minCap":16,
|
||||
"rate":1000,
|
||||
"supply": 200,
|
||||
"minCap":12,
|
||||
"rate":2000,
|
||||
"supply": 100,
|
||||
"whitelist":[
|
||||
{
|
||||
"address": "0xF16AB2EA0a7F7B28C267cbA3Ed211Ea5c6e27411",
|
||||
"min": 10,
|
||||
"max": 150
|
||||
}
|
||||
|
||||
|
||||
]
|
||||
}
|
||||
|
|
|
@ -471,7 +471,7 @@ test.describe('e2e test for TokenWizard2.0/DutchAuctionCrowdsale. v2.7.5 ', asyn
|
|||
|
||||
test.it('Crowdsale starts as scheduled',
|
||||
async function () {
|
||||
|
||||
let startTime;
|
||||
let counter = 180;
|
||||
do {
|
||||
startTime = await Utils.getDutchCrowdsaleStartTime(e2eWhitelist);
|
||||
|
@ -622,18 +622,18 @@ test.describe('e2e test for TokenWizard2.0/DutchAuctionCrowdsale. v2.7.5 ', asyn
|
|||
|
||||
test.it('Crowdsale has finished as scheduled',
|
||||
async function () {
|
||||
let endTime;
|
||||
let endT;
|
||||
let counter = 180;
|
||||
do {
|
||||
endTime = await Utils.getDutchCrowdsaleEndTime(e2eWhitelist);
|
||||
endT = await Utils.getDutchCrowdsaleEndTime(e2eWhitelist);
|
||||
logger.info("wait " + Date.now());
|
||||
logger.info("wait " + endTime);
|
||||
logger.info("wait " + endT);
|
||||
//console.log("Date.now() = " + Date.now());
|
||||
//console.log("endTime = " + endTime);
|
||||
//console.log("endTime = " + endT);
|
||||
//console.log("counter"+counter);
|
||||
await driver.sleep(1000);
|
||||
}
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endTime));
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endT));
|
||||
return await assert.equal(counter > 0, true, 'Test FAILED. Crowdsale has not finished in time ');
|
||||
});
|
||||
|
||||
|
@ -806,6 +806,7 @@ test.describe('e2e test for TokenWizard2.0/DutchAuctionCrowdsale. v2.7.5 ', asyn
|
|||
async function () {
|
||||
|
||||
let counter = 180;
|
||||
let startTime;
|
||||
do {
|
||||
startTime = await Utils.getDutchCrowdsaleStartTime(e2eMinCap);
|
||||
logger.info("wait " + Date.now());
|
||||
|
|
|
@ -24,7 +24,7 @@ const endDateForTestEarlier = "01/07/2049";
|
|||
const endTimeForTestLater = "420000";
|
||||
const endDateForTestLater = "420000";
|
||||
|
||||
test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', async function () {
|
||||
test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.8.0 ', async function () {
|
||||
this.timeout(2400000);//40 min
|
||||
this.slow(1800000);
|
||||
|
||||
|
@ -66,8 +66,13 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
test.before(async function () {
|
||||
|
||||
await Utils.copyEnvFromWizard();
|
||||
//await Utils.deployTWProxiesRegistry(8545,'./contracts/ProxiesRegistry');
|
||||
//await Utils.deployTWProxiesRegistryToRopsten(3,'./contracts/ProxiesRegistry');
|
||||
|
||||
//await Utils.copyEnvToWizard();
|
||||
//throw ("Stop");
|
||||
|
||||
const scenarioE2eMintedMinCap = './scenarios/scenarioE2eMintedMinCap.json';
|
||||
const scenarioE2eMintedWhitelist = './scenarios/scenarioE2eMintedWhitelist.json';
|
||||
const scenarioForUItests = './scenarios/scenarioUItests.json';
|
||||
|
@ -137,7 +142,7 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
|
||||
test.after(async function () {
|
||||
// Utils.killProcess(ganache);
|
||||
await Utils.sendEmail(tempOutputFile);
|
||||
//await Utils.sendEmail(tempOutputFile);
|
||||
let outputPath = Utils.getOutputPath();
|
||||
outputPath = outputPath + "/result" + Utils.getDate();
|
||||
await fs.ensureDirSync(outputPath);
|
||||
|
@ -494,6 +499,7 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
let owner = Owner;
|
||||
assert.equal(await owner.setMetaMaskAccount(), true, "Can not set Metamask account");
|
||||
let result = await owner.createMintedCappedCrowdsale(e2eWhitelist);
|
||||
logger.info("e2eWhitelist.proxyAddress " + e2eWhitelist.proxyAddress);
|
||||
logger.info("e2eWhitelist.executionID " + e2eWhitelist.executionID);
|
||||
logger.info("e2eWhitelist.networkID " + e2eWhitelist.networkID);
|
||||
logger.info("e2eWhitelist.sort " + e2eWhitelist.sort);
|
||||
|
@ -824,7 +830,7 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
let result = await investor.contribute(contribution);
|
||||
|
||||
let soldTokensAfter = await Utils.getTokensSold(e2eWhitelist);
|
||||
if (result) investor.tokenBalance = (soldTokensAfter - soldTokensBefore)/1e18 + investor.tokenBalance;
|
||||
if (result) investor.tokenBalance = (soldTokensAfter - soldTokensBefore) / 1e18 + investor.tokenBalance;
|
||||
|
||||
let shouldBe = e2eWhitelist.tiers[0].whitelist[0].max;
|
||||
let balance = await investor.getBalanceFromInvestPage(e2eWhitelist);
|
||||
|
@ -904,16 +910,17 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
async function () {
|
||||
let tierNumber = 1;
|
||||
let counter = 180;
|
||||
let endT;
|
||||
do {
|
||||
endTime = await Utils.getTiersEndTimeMintedCrowdsale(e2eWhitelist, tierNumber);
|
||||
logger.info("wait " + Date.now());
|
||||
logger.info("wait " + startTime);
|
||||
endT = await Utils.getTiersEndTimeMintedCrowdsale(e2eWhitelist, tierNumber);
|
||||
//logger.info("wait " + Date.now());
|
||||
//logger.info("wait " + endT);
|
||||
//console.log("Date.now() = " + Date.now());
|
||||
//console.log("startTime = " + endTime);
|
||||
await driver.sleep(1000);
|
||||
|
||||
}
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endTime));
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endT));
|
||||
return await assert.equal(counter > 0, true, 'Test FAILED. Tier #1 has not finished as scheduled');
|
||||
});
|
||||
///// TIER #2 Whitelist
|
||||
|
@ -952,14 +959,14 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
}
|
||||
console.log(result);
|
||||
console.log(contribution);
|
||||
// await driver.sleep(20000000000);
|
||||
// await driver.sleep(20000000000);
|
||||
return await assert.equal(result, false, "Test FAILED.Whitelisting is inherited");
|
||||
});
|
||||
|
||||
test.it("Contribution page: minContribution field contains correct minCap value for whitelisted investor",
|
||||
async function () {
|
||||
let investor = Investor1;
|
||||
//assert.equal(await investor.setMetaMaskAccount(), true, "Can not set Metamask account");
|
||||
//assert.equal(await inve stor.setMetaMaskAccount(), true, "Can not set Metamask account");
|
||||
assert.equal(await investor.openInvestPage(e2eWhitelist), true, 'Investor can not open Invest page');
|
||||
assert.equal(await investPage.waitUntilLoaderGone(), true, 'Loader displayed too long time');
|
||||
let result = await investPage.getMinContribution();
|
||||
|
@ -1014,7 +1021,7 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
let contribution = investor.maxCap;
|
||||
let result = await investor.contribute(contribution);
|
||||
let soldTokensAfter = await Utils.getTokensSold(e2eWhitelist);
|
||||
investor.tokenBalance = (soldTokensAfter - soldTokensBefore)/1e18 + investor.tokenBalance;
|
||||
investor.tokenBalance = (soldTokensAfter - soldTokensBefore) / 1e18 + investor.tokenBalance;
|
||||
return await assert.equal(result, true, "Test FAILED.Investor can not buy maxCap in first transaction");
|
||||
});
|
||||
|
||||
|
@ -1360,16 +1367,17 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
async function () {
|
||||
let tierNumber = 1;
|
||||
let counter = 180;
|
||||
let endT;
|
||||
do {
|
||||
endTime = await Utils.getTiersEndTimeMintedCrowdsale(e2eMinCap, tierNumber);
|
||||
logger.info("wait " + Date.now());
|
||||
logger.info("wait " + startTime);
|
||||
endT = await Utils.getTiersEndTimeMintedCrowdsale(e2eMinCap, tierNumber);
|
||||
//logger.info("wait " + Date.now());
|
||||
//logger.info("wait " + endT);
|
||||
//console.log("Date.now() = " + Date.now());
|
||||
//console.log("startTime = " + startTime);
|
||||
await driver.sleep(1000);
|
||||
|
||||
}
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endTime));
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endT));
|
||||
return await assert.equal(counter > 0, true, 'Test FAILED. Tier #1 has not finished as scheduled');
|
||||
});
|
||||
|
||||
|
@ -1394,7 +1402,7 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
return await assert.equal(result, true, 'Test FAILED. Countdown timer has incorrect status ');
|
||||
});
|
||||
|
||||
test.it('Should be individual minCap for each tier: if investor has bought in tier# then he is not able to buy less than minCap in first transaction in tier#2',
|
||||
test.it.skip('Should be individual minCap for each tier: if investor has bought in tier# then he is not able to buy less than minCap in first transaction in tier#2',
|
||||
async function () {
|
||||
let investor = Investor1;
|
||||
assert.equal(await investor.setMetaMaskAccount(), true, "Can not set Metamask account");
|
||||
|
@ -1544,16 +1552,17 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
async function () {
|
||||
let tierNumber = 2;
|
||||
let counter = 180;
|
||||
let endT;
|
||||
do {
|
||||
endTime = await Utils.getTiersEndTimeMintedCrowdsale(e2eMinCap, tierNumber);
|
||||
endT = await Utils.getTiersEndTimeMintedCrowdsale(e2eMinCap, tierNumber);
|
||||
logger.info("wait " + Date.now());
|
||||
logger.info("wait " + endTime);
|
||||
logger.info("wait " + endT);
|
||||
//console.log("Date.now() = " + Date.now());
|
||||
//console.log("startTime = " + startTime);
|
||||
await driver.sleep(1000);
|
||||
|
||||
}
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endTime));
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endT));
|
||||
return await assert.equal(counter > 0, true, 'Test FAILED. Tier #2 has not finished as scheduled');
|
||||
});
|
||||
//////// TIER#3 ///////////
|
||||
|
@ -1622,16 +1631,17 @@ test.describe('e2e test for TokenWizard2.0/MintedCappedCrowdsale. v2.7.5 ', asyn
|
|||
async function () {
|
||||
let tierNumber = 3;
|
||||
let counter = 180;
|
||||
let endT;
|
||||
do {
|
||||
endTime = await Utils.getTiersEndTimeMintedCrowdsale(e2eMinCap, tierNumber);
|
||||
endT = await Utils.getTiersEndTimeMintedCrowdsale(e2eMinCap, tierNumber);
|
||||
logger.info("wait " + Date.now());
|
||||
logger.info("wait " + endTime);
|
||||
logger.info("wait " + endT);
|
||||
//console.log("Date.now() = " + Date.now());
|
||||
//console.log("startTime = " + startTime);
|
||||
await driver.sleep(1000);
|
||||
|
||||
}
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endTime));
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= endT));
|
||||
return await assert.equal(counter > 0, true, 'Test FAILED. Tier #3 has not finished as scheduled');
|
||||
});
|
||||
///// AFTER END //////
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
let test = require('selenium-webdriver/testing');
|
||||
let assert = require('assert');
|
||||
const fs = require('fs-extra');
|
||||
///////////////////////////////////////////////////////
|
||||
const WizardWelcome = require('../pages/WizardWelcome.js').WizardWelcome;
|
||||
const WizardStep1 = require('../pages/WizardStep1.js').WizardStep1;
|
||||
const WizardStep2 = require('../pages/WizardStep2.js').WizardStep2;
|
||||
const WizardStep3 = require('../pages/WizardStep3.js').WizardStep3;
|
||||
const WizardStep4 = require('../pages/WizardStep4.js').WizardStep4;
|
||||
const TierPage = require('../pages/TierPage.js').TierPage;
|
||||
const ReservedTokensPage = require('../pages/ReservedTokensPage.js').ReservedTokensPage;
|
||||
const CrowdsalePage = require('../pages/CrowdsalePage.js').CrowdsalePage;
|
||||
const InvestPage = require('../pages/ContributionPage.js').InvestPage;
|
||||
const ManagePage = require('../pages/ManagePage.js').ManagePage;
|
||||
const logger = require('../entity/Logger.js').logger;
|
||||
const tempOutputPath = require('../entity/Logger.js').tempOutputPath;
|
||||
const Utils = require('../utils/Utils.js').Utils;
|
||||
const MetaMask = require('../pages/MetaMask.js').MetaMask;
|
||||
const User = require("../entity/User.js").User;
|
||||
const Crowdsale = require('../entity/Crowdsale.js').Crowdsale;
|
||||
const smallAmount = 0.1;
|
||||
const endTimeForTestEarlier = "01:23";
|
||||
const endDateForTestEarlier = "01/07/2049";
|
||||
const endTimeForTestLater = "420000";
|
||||
const endDateForTestLater = "420000";
|
||||
|
||||
test.describe('POA token-wizard. Test MintedCappedCrowdsale', async function () {
|
||||
this.timeout(2400000);//40 min
|
||||
this.slow(1800000);
|
||||
const user3_56B2File ='./users/user3_56B2.json';
|
||||
const user8545_56B2File = './users/user8545_56B2.json';//Owner
|
||||
const user8545_F16AFile = './users/user8545_F16A.json';//Investor1 - whitelisted for Tier#1 before deployment
|
||||
const user8545_f5aAFile = './users/user8545_f5aA.json';//Investor2 - added from manage page before start
|
||||
const user8545_ecDFFile = './users/user8545_ecDF.json';//Reserved address, also wh investor that added after start time
|
||||
const user8545_dDdCFile = './users/user8545_dDdC.json';//Investor3 - whitelisted for Tier#2 before deployment
|
||||
|
||||
let driver;
|
||||
let Owner;
|
||||
let Investor1;
|
||||
let Investor2;
|
||||
let Investor3;
|
||||
let ReservedAddress;
|
||||
|
||||
let metaMask;
|
||||
let welcomePage;
|
||||
let wizardStep1;
|
||||
let wizardStep2;
|
||||
let wizardStep3;
|
||||
let wizardStep4;
|
||||
let tierPage;
|
||||
let reservedTokensPage;
|
||||
let investPage;
|
||||
let startURL;
|
||||
let crowdsaleForUItests;
|
||||
let e2eMinCap;
|
||||
let e2eWhitelist;
|
||||
let e2eMultitier;
|
||||
let mngPage;
|
||||
let balance;
|
||||
let endTime;
|
||||
let endDate;
|
||||
|
||||
let MintedDecimalsWhitelist;
|
||||
let DutchDecimalsWhitelist;
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
test.before(async function () {
|
||||
logger.info("test decimals ");
|
||||
await Utils.copyEnvFromWizard();
|
||||
|
||||
const scenarioDutchDecimalsWhitelist = './scenarios/scenarioDutchDecimalsWhitelist.json';
|
||||
const scenarioMintedDecimalsWhitelist = './scenarios/scenarioMintedDecimalsWhitelist.json'
|
||||
|
||||
|
||||
//DutchDecimalsWhitelist = await Utils.getDutchCrowdsaleInstance(scenarioDutchDecimalsWhitelist);
|
||||
MintedDecimalsWhitelist = await Utils.getMintedCrowdsaleInstance(scenarioMintedDecimalsWhitelist);
|
||||
startURL = await Utils.getStartURL();
|
||||
driver = await Utils.startBrowserWithMetamask();
|
||||
Owner = new User(driver, user8545_56B2File);
|
||||
await Utils.receiveEth(Owner, 20);
|
||||
logger.info("Owner = " + Owner.account);
|
||||
logger.info("Owner's balance = " + await Utils.getBalance(Owner) / 1e18 + " Eth");
|
||||
|
||||
metaMask = new MetaMask(driver);
|
||||
await metaMask.activate();//return activated Metamask and empty page
|
||||
await Owner.setMetaMaskAccount();
|
||||
|
||||
welcomePage = new WizardWelcome(driver, startURL);
|
||||
wizardStep1 = new WizardStep1(driver);
|
||||
wizardStep2 = new WizardStep2(driver);
|
||||
wizardStep3 = new WizardStep3(driver);
|
||||
wizardStep4 = new WizardStep4(driver);
|
||||
investPage = new InvestPage(driver);
|
||||
reservedTokensPage = new ReservedTokensPage(driver);
|
||||
mngPage = new ManagePage(driver);
|
||||
//tierPage = new TierPage(driver, e2eRopsten.tiers[0]);
|
||||
|
||||
});
|
||||
|
||||
test.after(async function () {
|
||||
// Utils.killProcess(ganache);
|
||||
//await Utils.sendEmail(tempOutputFile);
|
||||
let outputPath = Utils.getOutputPath();
|
||||
outputPath = outputPath + "/result" + Utils.getDate();
|
||||
await fs.ensureDirSync(outputPath);
|
||||
await fs.copySync(tempOutputPath, outputPath);
|
||||
//await fs.remove(tempOutputPath);
|
||||
//await driver.quit();
|
||||
});
|
||||
|
||||
//////////////////////// Test SUITE #1 /////////////////////////////
|
||||
test.it('Owner can create crowdsale:Minted,whitelist',
|
||||
async function () {
|
||||
let owner = Owner;
|
||||
assert.equal(await owner.setMetaMaskAccount(), true, "Can not set Metamask account");
|
||||
MintedDecimalsWhitelist.decimals = 0;
|
||||
console.log("Decimals = "+ MintedDecimalsWhitelist.decimals);
|
||||
let result = await owner.createMintedCappedCrowdsale(MintedDecimalsWhitelist);
|
||||
return await assert.equal(result, true, 'Test FAILED. Crowdsale has not created ');
|
||||
});
|
||||
test.it('Crowdsale starts as scheduled',
|
||||
async function () {
|
||||
let startTime;
|
||||
let counter = 180;
|
||||
do {
|
||||
startTime = await Utils.getMintedCrowdsaleStartTime(MintedDecimalsWhitelist);
|
||||
logger.info("wait " + Date.now());
|
||||
logger.info("wait " + startTime);
|
||||
//console.log("Date.now() = " + Date.now());
|
||||
//console.log("startTime = " + startTime);
|
||||
//console.log("counter"+counter);
|
||||
await driver.sleep(1000);
|
||||
}
|
||||
while (counter-- > 0 && (Date.now() / 1000 <= startTime));
|
||||
return await assert.equal(counter > 0, true, 'Test FAILED. Tier has not start in time ');
|
||||
});
|
||||
|
||||
test.it('Investor is able to buy amount equal minCap',
|
||||
async function () {
|
||||
let investor = Owner;
|
||||
//assert.equal(await investor.setMetaMaskAccount(), true, "Can not set Metamask account");
|
||||
let contribution = MintedDecimalsWhitelist.tiers[0].whitelist[0].min;
|
||||
investor.tokenBalance += contribution;
|
||||
let result = await investor.openInvestPage(MintedDecimalsWhitelist)
|
||||
&& await investor.contribute(contribution);
|
||||
return await assert.equal(result, true, 'Test FAILED. Investor can not buy ');
|
||||
});
|
||||
|
||||
test.it('Investors balance is properly changed after purchase ',
|
||||
async function () {
|
||||
let investor = Owner;
|
||||
let balance= await investor.getTokenBalance(MintedDecimalsWhitelist);
|
||||
console.log("Balance in wei = "+balance);
|
||||
let balanceTokens = balance/Math.pow(10,MintedDecimalsWhitelist.decimals);
|
||||
console.log("Balance in tokens = "+balanceTokens);
|
||||
console.log("ShouldBe = " + MintedDecimalsWhitelist.tiers[0].whitelist[0].min);
|
||||
let result = (balanceTokens === MintedDecimalsWhitelist.tiers[0].whitelist[0].min)
|
||||
return await assert.equal(result, true, "Test FAILED. Investor can buy but balance did not changed");
|
||||
});
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
|
||||
});
|
171
utils/Utils.js
171
utils/Utils.js
|
@ -325,41 +325,41 @@ class Utils {
|
|||
return (Math.abs(balanceShouldBe - balanceEthOwnerAfter / 1e18) < delta);
|
||||
}
|
||||
|
||||
static async getEnvAddressMintedIDXAddress() {
|
||||
static async getFromEnvMintedIDXAddress() {
|
||||
logger.info("Utils:getEnvAddressMintedInitCrowdsale");
|
||||
require('dotenv').config();
|
||||
return Object.values(JSON.parse(process.env.REACT_APP_MINTED_CAPPED_IDX_ADDRESS))[0];
|
||||
}
|
||||
|
||||
static async getEnvAddressDutchIDXAddress() {
|
||||
static async getFromEnvDutchIDXAddress() {
|
||||
logger.info("Utils:getEnvAddressDutchInitCrowdsale");
|
||||
require('dotenv').config();
|
||||
return Object.values(JSON.parse(process.env.REACT_APP_DUTCH_IDX_ADDRESS))[0];
|
||||
}
|
||||
|
||||
static async getEnvAddressAbstractStorage() {
|
||||
static async getFromEnvAbstractStorageAddress() {
|
||||
logger.info("Utils:getEnvAddressRegistryStorage");
|
||||
require('dotenv').config();
|
||||
return Object.values(JSON.parse(process.env.REACT_APP_ABSTRACT_STORAGE_ADDRESS))[0];
|
||||
}
|
||||
|
||||
static async getEnvNetworkId() {
|
||||
static async getFromEnvNetworkId() {
|
||||
logger.info("Utils:getEnvNetworkId");
|
||||
require('dotenv').config();
|
||||
return Object.keys(JSON.parse(process.env.REACT_APP_REGISTRY_STORAGE_ADDRESS))[0];
|
||||
}
|
||||
|
||||
static async getContractAddressInitCrowdsale(crowdsale) {
|
||||
logger.info("Utils:getContractAddressInitCrowdsale");
|
||||
static async getContractAddressIdx(crowdsale) {
|
||||
logger.info("Utils:getContractAddressIdx");
|
||||
switch (crowdsale.sort) {
|
||||
case 'minted':
|
||||
return Utils.getEnvAddressMintedIDXAddress();
|
||||
return Utils.getFromEnvMintedIDXAddress();
|
||||
break;
|
||||
case 'dutch':
|
||||
return Utils.getEnvAddressDutchIDXAddress();
|
||||
return Utils.getFromEnvDutchIDXAddress();
|
||||
break;
|
||||
default:
|
||||
return Utils.getEnvAddressMintedIDXAddress();
|
||||
return Utils.getFromEnvMintedIDXAddress();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -382,6 +382,7 @@ class Utils {
|
|||
}
|
||||
|
||||
static async copyEnvFromWizard() {
|
||||
logger.info("Utils:copyEnvFromWizard")
|
||||
try {
|
||||
fs.copySync('../../.env', './.env', {overwrite: true});
|
||||
return true;
|
||||
|
@ -393,6 +394,18 @@ class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
static async copyEnvToWizard() {
|
||||
try {
|
||||
fs.copySync('./.env', '../../.env', {overwrite: true});
|
||||
return true;
|
||||
}
|
||||
catch (err) {
|
||||
logger.info("! Can't find .env file in e2e directory !");
|
||||
logger.info(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static async sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
@ -447,8 +460,8 @@ class Utils {
|
|||
if (crowdsale.sort === _minted) return false;
|
||||
let web3 = Utils.getWeb3Instance(crowdsale.networkID);
|
||||
const abi = await Utils.getContractABIInitCrowdsale(crowdsale);
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getEnvAddressDutchIDXAddress());
|
||||
let result = await myContract.methods.getCrowdsaleStartAndEndTimes(await Utils.getEnvAddressAbstractStorage(), crowdsale.executionID).call();
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getFromEnvDutchIDXAddress());
|
||||
let result = await myContract.methods.getCrowdsaleStartAndEndTimes(await Utils.getFromEnvAbstractStorageAddress(), crowdsale.executionID).call();
|
||||
return result.start_time;
|
||||
}
|
||||
|
||||
|
@ -457,8 +470,8 @@ class Utils {
|
|||
if (crowdsale.sort === _minted) return false;
|
||||
let web3 = Utils.getWeb3Instance(crowdsale.networkID);
|
||||
const abi = await Utils.getContractABIInitCrowdsale(crowdsale);
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getEnvAddressDutchIDXAddress());
|
||||
let result = await myContract.methods.getCrowdsaleStartAndEndTimes(await Utils.getEnvAddressAbstractStorage(), crowdsale.executionID).call();
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getFromEnvDutchIDXAddress());
|
||||
let result = await myContract.methods.getCrowdsaleStartAndEndTimes(await Utils.getFromEnvAbstractStorageAddress(), crowdsale.executionID).call();
|
||||
return result.end_time;
|
||||
}
|
||||
|
||||
|
@ -468,10 +481,10 @@ class Utils {
|
|||
let web3 = Utils.getWeb3Instance(crowdsale.networkID);
|
||||
const abi = await Utils.getContractABIInitCrowdsale(crowdsale);
|
||||
let idx;
|
||||
if (crowdsale.sort === _minted) idx = await Utils.getEnvAddressMintedIDXAddress();
|
||||
else idx = await Utils.getEnvAddressDutchIDXAddress();
|
||||
if (crowdsale.sort === _minted) idx = await Utils.getFromEnvMintedIDXAddress();
|
||||
else idx = await Utils.getFromEnvDutchIDXAddress();
|
||||
let myContract = new web3.eth.Contract(abi, idx);
|
||||
let result = await myContract.methods.getTokensSold(await Utils.getEnvAddressAbstractStorage(), crowdsale.executionID).call();
|
||||
let result = await myContract.methods.getTokensSold(await Utils.getFromEnvAbstractStorageAddress(), crowdsale.executionID).call();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -499,8 +512,8 @@ class Utils {
|
|||
if (crowdsale.sort === _dutch) return false;
|
||||
let web3 = Utils.getWeb3Instance(crowdsale.networkID);
|
||||
const abi = await Utils.getContractABIInitCrowdsale(crowdsale);
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getEnvAddressMintedIDXAddress());
|
||||
let result = await myContract.methods.getCrowdsaleStartAndEndTimes(await Utils.getEnvAddressAbstractStorage(), crowdsale.executionID).call();
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getFromEnvMintedIDXAddress());
|
||||
let result = await myContract.methods.getCrowdsaleStartAndEndTimes(await Utils.getFromEnvAbstractStorageAddress(), crowdsale.executionID).call();
|
||||
return result.start_time;
|
||||
}
|
||||
|
||||
|
@ -509,11 +522,129 @@ class Utils {
|
|||
if (crowdsale.sort === _dutch) return false;
|
||||
let web3 = Utils.getWeb3Instance(crowdsale.networkID);
|
||||
const abi = await Utils.getContractABIInitCrowdsale(crowdsale);
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getEnvAddressMintedIDXAddress());
|
||||
let result = await myContract.methods.getTierStartAndEndDates(await Utils.getEnvAddressAbstractStorage(), crowdsale.executionID, tierNumber - 1).call();
|
||||
let myContract = new web3.eth.Contract(abi, await Utils.getFromEnvMintedIDXAddress());
|
||||
let result = await myContract.methods.getTierStartAndEndDates(await Utils.getFromEnvAbstractStorageAddress(), crowdsale.executionID, tierNumber - 1).call();
|
||||
return result.tier_end;
|
||||
}
|
||||
|
||||
static async deployContract(web3, abi, bin, from, parameters) {
|
||||
console.log("Utils: deployContract")
|
||||
console.log("from address= " + from)
|
||||
const contract = new web3.eth.Contract(abi, {from});
|
||||
const gas = 8900000;
|
||||
const gasPrice = '10000000000';
|
||||
console.log("parametersabstractStorage: " + parameters[0]);
|
||||
console.log("parametersmintedIdx: " + parameters[1]);
|
||||
console.log("parametersdutchIdx: " + parameters[2]);
|
||||
return contract
|
||||
.deploy(
|
||||
{
|
||||
data: bin,
|
||||
arguments: parameters
|
||||
}
|
||||
)
|
||||
.send({
|
||||
from,
|
||||
gas,
|
||||
gasPrice
|
||||
})
|
||||
}
|
||||
|
||||
static async deployTWProxiesRegistry(network, registryPath) {
|
||||
logger.info("Utils:deployTWProxiesRegistry ");
|
||||
|
||||
//const web3 = await new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
|
||||
const web3 = await Utils.getWeb3Instance(network);
|
||||
const registryAbi = await JSON.parse(fs.readFileSync(`${registryPath}.abi`).toString());
|
||||
let registryBin = await fs.readFileSync(`${registryPath}.bin`).toString();
|
||||
if (registryBin.slice(0, 2) !== '0x' && registryBin.slice(0, 2) !== '0X') {
|
||||
registryBin = '0x' + registryBin;
|
||||
}
|
||||
|
||||
let abstractStorage = await Utils.getFromEnvAbstractStorageAddress();
|
||||
let mintedIdx = await Utils.getFromEnvMintedIDXAddress();
|
||||
let dutchIdx = await Utils.getFromEnvDutchIDXAddress();
|
||||
|
||||
let account = await web3.eth.getAccounts().then((accounts) => {
|
||||
return accounts[0]
|
||||
});
|
||||
let contract = await Utils.deployContract(web3, registryAbi, registryBin, account, [abstractStorage, mintedIdx, dutchIdx]);
|
||||
|
||||
const networkID = await web3.eth.net.getId();
|
||||
const registryAddress = contract._address;
|
||||
let envContent = `REACT_APP_TW_PROXIES_REGISTRY_ADDRESS='{"${networkID}":"${registryAddress}"}'`;
|
||||
console.log(envContent);
|
||||
console.log("abstractStorage: " + abstractStorage);
|
||||
console.log("mintedIdx: " + mintedIdx);
|
||||
console.log("dutchIdx: " + dutchIdx);
|
||||
|
||||
if (await !fs.existsSync("./.env")) await fs.writeFileSync("./.env");
|
||||
await fs.appendFileSync("./.env", envContent);
|
||||
}
|
||||
|
||||
static async deployTWProxiesRegistryToRopsten(network, registryPath) {
|
||||
logger.info("Utils:deployTWProxiesRegistry ");
|
||||
|
||||
//const web3 = await new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
|
||||
const web3 = await Utils.getWeb3Instance(3);
|
||||
const registryAbi = await JSON.parse(fs.readFileSync(`${registryPath}.abi`).toString());
|
||||
let registryBin = await fs.readFileSync(`${registryPath}.bin`).toString();
|
||||
if (registryBin.slice(0, 2) !== '0x' && registryBin.slice(0, 2) !== '0X') {
|
||||
registryBin = '0x' + registryBin;
|
||||
}
|
||||
|
||||
let abstractStorage = await Utils.getFromEnvAbstractStorageAddress();
|
||||
let mintedIdx = await Utils.getFromEnvMintedIDXAddress();
|
||||
let dutchIdx = await Utils.getFromEnvDutchIDXAddress();
|
||||
|
||||
let privateKey = "0xba98116a7d4b98f22f113c59448b9cc69f916d75f35d51f088b64b483fd0b8ca";
|
||||
let account = web3.eth.accounts.privateKeyToAccount(privateKey);
|
||||
console.log(account.address);
|
||||
let bal = await web3.eth.getBalance(account.address.toString())
|
||||
console.log("bal= " + bal / 1e18);
|
||||
console.log("abstractStorage: " + abstractStorage);
|
||||
console.log("mintedIdx: " + mintedIdx);
|
||||
console.log("dutchIdx: " + dutchIdx);
|
||||
const networkID = await web3.eth.net.getId();
|
||||
console.log("networkID: " + networkID);
|
||||
/*
|
||||
let account = await web3.eth.getAccounts().then((accounts) => {
|
||||
return accounts[0]
|
||||
});*/
|
||||
let contract = await Utils.deployContract(web3, registryAbi, registryBin, account.address, [abstractStorage, mintedIdx, dutchIdx]);
|
||||
|
||||
const registryAddress = contract._address;
|
||||
let envContent = `REACT_APP_TW_PROXIES_REGISTRY_ADDRESS='{"${networkID}":"${registryAddress}"}'`;
|
||||
console.log(envContent);
|
||||
|
||||
if (await !fs.existsSync("./.env")) await fs.writeFileSync("./.env");
|
||||
await fs.appendFileSync("./.env", envContent);
|
||||
}
|
||||
|
||||
//////////// PROXY /////////////////////////////////////
|
||||
|
||||
static async getContractABIProxy(crowdsale) {
|
||||
logger.info("Utils:getContractABIProxy");
|
||||
let path = './contracts/Proxies.abi';
|
||||
return await JSON.parse(fs.readFileSync(path).toString());
|
||||
}
|
||||
|
||||
static async getProxyExecID(crowdsale) {
|
||||
logger.info("getProxyExecID");
|
||||
try {
|
||||
let web3 = Utils.getWeb3Instance(crowdsale.networkID);
|
||||
const abi = await Utils.getContractABIProxy(crowdsale);
|
||||
let myContract = new web3.eth.Contract(abi, crowdsale.proxyAddress.toString());
|
||||
let result = await myContract.methods.app_exec_id().call();
|
||||
logger.info("app_exec_id " + result);
|
||||
return result;
|
||||
}
|
||||
catch (err) {
|
||||
logger.info("Can't read contract. Error: " + err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
Loading…
Reference in New Issue