├── README.md ├── backend └── contract.go ├── contracts └── WemixToken.sol ├── go.mod ├── go.sum ├── test ├── WemixToken_test.go └── helper.go └── wemix_token_audit_report_20200624.pdf /README.md: -------------------------------------------------------------------------------- 1 | # Wemix Token Smart Contract 2 | 3 | ## Requirements 4 | 5 | - Solidity 6.3 6 | 7 | ## Security Audit 8 | 9 | - [AuditReport](wemix_token_audit_report_20200624.pdf) by Certik 10 | 11 | ## Contract Deploy 12 | 13 | - [WemixToken](https://scope.klaytn.com/token/0x5096db80b21ef45230c9e423c373f1fc9c0198dd?tabId=kctTransfer) in Klaytn 14 | -------------------------------------------------------------------------------- /backend/contract.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "encoding/json" 7 | "fmt" 8 | "math/big" 9 | "strings" 10 | 11 | "github.com/ethereum/go-ethereum" 12 | "github.com/ethereum/go-ethereum/accounts/abi" 13 | "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" 14 | "github.com/ethereum/go-ethereum/common" 15 | "github.com/ethereum/go-ethereum/common/compiler" 16 | "github.com/ethereum/go-ethereum/core/types" 17 | "github.com/ethereum/go-ethereum/crypto" 18 | ) 19 | 20 | //Contract struct holds data before compilation and information after compilation. 21 | type Contract struct { 22 | File string 23 | Name string 24 | Backend *backends.SimulatedBackend 25 | OwnerKey *ecdsa.PrivateKey 26 | Owner common.Address 27 | Info *compiler.ContractInfo 28 | ConstructorInputs []interface{} 29 | Abi *abi.ABI 30 | Code []byte 31 | Address common.Address 32 | BlockDeployed *big.Int 33 | } 34 | 35 | //NewContract is to create simulated backend and compile solidity code 36 | func NewContract(file, name string) (*Contract, error) { 37 | 38 | ownerKey, _ := crypto.GenerateKey() 39 | 40 | r := &Contract{ 41 | File: file, 42 | Name: name, 43 | //creates a new binding backend using a simulated blockchain 44 | Backend: backends.NewSimulatedBackend( 45 | nil, 46 | 10000000, 47 | ), 48 | OwnerKey: ownerKey, 49 | Owner: crypto.PubkeyToAddress(ownerKey.PublicKey), 50 | } 51 | //compile 52 | if err := r.compile(); err != nil { 53 | return nil, err 54 | } 55 | 56 | return r, nil 57 | } 58 | 59 | func (p *Contract) compile() error { 60 | contracts, err := compiler.CompileSolidity("", p.File) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | //Get the contract to test from the compiled contracts. 66 | contract, ok := contracts[fmt.Sprintf("%s:%s", p.File, p.Name)] 67 | if ok == false { 68 | fmt.Errorf("%s contract is not here", p.Name) 69 | } 70 | //make abi.ABI instance 71 | abiBytes, err := json.Marshal(contract.Info.AbiDefinition) 72 | if err != nil { 73 | return err 74 | } 75 | abi, err := abi.JSON(strings.NewReader(string(abiBytes))) 76 | if err != nil { 77 | return err 78 | } 79 | p.Info = &contract.Info 80 | p.Abi = &abi 81 | p.Code = common.FromHex(contract.Code) 82 | return nil 83 | } 84 | 85 | //Deploy makes creation contract tx and receives the result by receipt. 86 | func (p *Contract) Deploy(args ...interface{}) error { 87 | input, err := p.Abi.Pack("", args...) //constructor's inputs 88 | if err != nil { 89 | return err 90 | } 91 | 92 | p.ConstructorInputs = args // Save for later checkout 93 | 94 | //make tx for contract creation 95 | tx := types.NewContractCreation(0, big.NewInt(0), 3000000, big.NewInt(0), append(p.Code, input...)) 96 | //signing 97 | tx, _ = types.SignTx(tx, types.HomesteadSigner{}, p.OwnerKey) 98 | //send tx to simulated backend 99 | if err := p.Backend.SendTransaction(context.Background(), tx); err != nil { 100 | return err 101 | } 102 | //make block 103 | p.Backend.Commit() 104 | 105 | //get contract address through receipt 106 | receipt, err := p.Backend.TransactionReceipt(context.Background(), tx.Hash()) 107 | if err != nil { 108 | return err 109 | } 110 | if receipt.Status != 1 { 111 | return fmt.Errorf("status of deploy tx receipt: %v", receipt.Status) 112 | } 113 | //get contract's address and block deployed from the receipt 114 | p.Address = receipt.ContractAddress 115 | p.BlockDeployed = receipt.BlockNumber 116 | return nil 117 | } 118 | 119 | // Call is Invokes a view method with args and then receive the result unpacked. 120 | func (p *Contract) Call(result interface{}, method string, args ...interface{}) error { 121 | if input, err := p.Abi.Pack(method, args...); err != nil { 122 | return err 123 | } else { 124 | msg := ethereum.CallMsg{From: common.Address{}, To: &p.Address, Data: input} 125 | 126 | out := result 127 | if output, err := p.Backend.CallContract(context.TODO(), msg, nil); err != nil { 128 | return err 129 | } else if err := p.Abi.Unpack(out, method, output); err != nil { 130 | return err 131 | } 132 | } 133 | return nil 134 | } 135 | 136 | //LowCall returns method's output in a different way than Call. 137 | func (p *Contract) LowCall(method string, args ...interface{}) ([]interface{}, error) { 138 | if input, err := p.Abi.Pack(method, args...); err != nil { 139 | return nil, err 140 | } else { 141 | msg := ethereum.CallMsg{From: common.Address{}, To: &p.Address, Data: input} 142 | if out, err := p.Backend.CallContract(context.TODO(), msg, nil); err != nil { 143 | return []interface{}{}, err 144 | } else { 145 | if ret, err := p.Abi.Methods[method].Outputs.UnpackValues(out); err != nil { 146 | return []interface{}{}, err 147 | } else { 148 | return ret, nil 149 | } 150 | } 151 | } 152 | } 153 | 154 | //Execute executes the contract's method. For that, take tx with signer's key, method and inputs, 155 | //and then send it to the simulated backend, and return the receipt. 156 | func (p *Contract) Execute(key *ecdsa.PrivateKey, method string, args ...interface{}) (*types.Receipt, error) { 157 | if key == nil { 158 | key = p.OwnerKey 159 | } 160 | 161 | data, err := p.Abi.Pack(method, args...) 162 | if err != nil { 163 | return nil, err 164 | } 165 | 166 | nonce, err := p.Backend.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(key.PublicKey)) 167 | if err != nil { 168 | return nil, err 169 | } 170 | 171 | tx, err := types.SignTx(types.NewTransaction(nonce, p.Address, new(big.Int), uint64(10000000), big.NewInt(0), data), 172 | types.HomesteadSigner{}, key) 173 | if err != nil { 174 | return nil, err 175 | } 176 | if err := p.Backend.SendTransaction(context.Background(), tx); err != nil { 177 | return nil, err 178 | } 179 | p.Backend.Commit() 180 | 181 | receipt, err := p.Backend.TransactionReceipt(context.Background(), tx.Hash()) 182 | if err != nil { 183 | return nil, err 184 | } 185 | 186 | return receipt, nil 187 | } 188 | -------------------------------------------------------------------------------- /contracts/WemixToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >= 0.6.0 <0.7.0; 2 | 3 | 4 | /** 5 | * @dev Interface of the ERC20 standard as defined in the EIP. Does not include 6 | * the optional functions; to access them see {ERC20Detailed}. 7 | */ 8 | interface IERC20 { 9 | /** 10 | * @dev Returns the amount of tokens in existence. 11 | */ 12 | function totalSupply() external view returns (uint256); 13 | 14 | /** 15 | * @dev Returns the amount of tokens owned by `account`. 16 | */ 17 | function balanceOf(address account) external view returns (uint256); 18 | 19 | /** 20 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 21 | * 22 | * Returns a boolean value indicating whether the operation succeeded. 23 | * 24 | * Emits a {Transfer} event. 25 | */ 26 | function transfer(address recipient, uint256 amount) external returns (bool); 27 | 28 | /** 29 | * @dev Returns the remaining number of tokens that `spender` will be 30 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 31 | * zero by default. 32 | * 33 | * This value changes when {approve} or {transferFrom} are called. 34 | */ 35 | function allowance(address owner, address spender) external view returns (uint256); 36 | 37 | /** 38 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 39 | * 40 | * Returns a boolean value indicating whether the operation succeeded. 41 | * 42 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 43 | * that someone may use both the old and the new allowance by unfortunate 44 | * transaction ordering. One possible solution to mitigate this race 45 | * condition is to first reduce the spender's allowance to 0 and set the 46 | * desired value afterwards: 47 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 48 | * 49 | * Emits an {Approval} event. 50 | */ 51 | function approve(address spender, uint256 amount) external returns (bool); 52 | 53 | /** 54 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 55 | * allowance mechanism. `amount` is then deducted from the caller's 56 | * allowance. 57 | * 58 | * Returns a boolean value indicating whether the operation succeeded. 59 | * 60 | * Emits a {Transfer} event. 61 | */ 62 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 63 | 64 | /** 65 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 66 | * another (`to`). 67 | * 68 | * Note that `value` may be zero. 69 | */ 70 | event Transfer(address indexed from, address indexed to, uint256 value); 71 | 72 | /** 73 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 74 | * a call to {approve}. `value` is the new allowance. 75 | */ 76 | event Approval(address indexed owner, address indexed spender, uint256 value); 77 | } 78 | 79 | /** 80 | * @dev Optional functions from the ERC20 standard. 81 | */ 82 | abstract contract ERC20Detailed is IERC20 { 83 | string private _name; 84 | string private _symbol; 85 | uint8 private _decimals; 86 | 87 | /** 88 | * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of 89 | * these values are immutable: they can only be set once during 90 | * construction. 91 | */ 92 | constructor (string memory name, string memory symbol, uint8 decimals) public { 93 | _name = name; 94 | _symbol = symbol; 95 | _decimals = decimals; 96 | } 97 | 98 | /** 99 | * @dev Returns the name of the token. 100 | */ 101 | function name() public view returns (string memory) { 102 | return _name; 103 | } 104 | 105 | /** 106 | * @dev Returns the symbol of the token, usually a shorter version of the 107 | * name. 108 | */ 109 | function symbol() public view returns (string memory) { 110 | return _symbol; 111 | } 112 | 113 | /** 114 | * @dev Returns the number of decimals used to get its user representation. 115 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 116 | * be displayed to a user as `5,05` (`505 / 10 ** 2`). 117 | * 118 | * Tokens usually opt for a value of 18, imitating the relationship between 119 | * Ether and Wei. 120 | * 121 | * NOTE: This information is only used for _display_ purposes: it in 122 | * no way affects any of the arithmetic of the contract, including 123 | * {IERC20-balanceOf} and {IERC20-transfer}. 124 | */ 125 | function decimals() public view returns (uint8) { 126 | return _decimals; 127 | } 128 | } 129 | 130 | /** 131 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 132 | * checks. 133 | * 134 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 135 | * in bugs, because programmers usually assume that an overflow raises an 136 | * error, which is the standard behavior in high level programming languages. 137 | * `SafeMath` restores this intuition by reverting the transaction when an 138 | * operation overflows. 139 | * 140 | * Using this library instead of the unchecked operations eliminates an entire 141 | * class of bugs, so it's recommended to use it always. 142 | */ 143 | library SafeMath { 144 | /** 145 | * @dev Returns the addition of two unsigned integers, reverting on 146 | * overflow. 147 | * 148 | * Counterpart to Solidity's `+` operator. 149 | * 150 | * Requirements: 151 | * - Addition cannot overflow. 152 | */ 153 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 154 | uint256 c = a + b; 155 | require(c >= a, "SafeMath: addition overflow"); 156 | 157 | return c; 158 | } 159 | 160 | /** 161 | * @dev Returns the subtraction of two unsigned integers, reverting on 162 | * overflow (when the result is negative). 163 | * 164 | * Counterpart to Solidity's `-` operator. 165 | * 166 | * Requirements: 167 | * - Subtraction cannot overflow. 168 | */ 169 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 170 | return sub(a, b, "SafeMath: subtraction overflow"); 171 | } 172 | 173 | /** 174 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 175 | * overflow (when the result is negative). 176 | * 177 | * Counterpart to Solidity's `-` operator. 178 | * 179 | * Requirements: 180 | * - Subtraction cannot overflow. 181 | * 182 | * _Available since v2.4.0._ 183 | */ 184 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 185 | require(b <= a, errorMessage); 186 | uint256 c = a - b; 187 | 188 | return c; 189 | } 190 | 191 | /** 192 | * @dev Returns the multiplication of two unsigned integers, reverting on 193 | * overflow. 194 | * 195 | * Counterpart to Solidity's `*` operator. 196 | * 197 | * Requirements: 198 | * - Multiplication cannot overflow. 199 | */ 200 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 201 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 202 | // benefit is lost if 'b' is also tested. 203 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 204 | if (a == 0) { 205 | return 0; 206 | } 207 | 208 | uint256 c = a * b; 209 | require(c / a == b, "SafeMath: multiplication overflow"); 210 | 211 | return c; 212 | } 213 | 214 | /** 215 | * @dev Returns the integer division of two unsigned integers. Reverts on 216 | * division by zero. The result is rounded towards zero. 217 | * 218 | * Counterpart to Solidity's `/` operator. Note: this function uses a 219 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 220 | * uses an invalid opcode to revert (consuming all remaining gas). 221 | * 222 | * Requirements: 223 | * - The divisor cannot be zero. 224 | */ 225 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 226 | return div(a, b, "SafeMath: division by zero"); 227 | } 228 | 229 | /** 230 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 231 | * division by zero. The result is rounded towards zero. 232 | * 233 | * Counterpart to Solidity's `/` operator. Note: this function uses a 234 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 235 | * uses an invalid opcode to revert (consuming all remaining gas). 236 | * 237 | * Requirements: 238 | * - The divisor cannot be zero. 239 | * 240 | * _Available since v2.4.0._ 241 | */ 242 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 243 | // Solidity only automatically asserts when dividing by 0 244 | require(b > 0, errorMessage); 245 | uint256 c = a / b; 246 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 247 | 248 | return c; 249 | } 250 | 251 | /** 252 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 253 | * Reverts when dividing by zero. 254 | * 255 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 256 | * opcode (which leaves remaining gas untouched) while Solidity uses an 257 | * invalid opcode to revert (consuming all remaining gas). 258 | * 259 | * Requirements: 260 | * - The divisor cannot be zero. 261 | */ 262 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 263 | return mod(a, b, "SafeMath: modulo by zero"); 264 | } 265 | 266 | /** 267 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 268 | * Reverts with custom message when dividing by zero. 269 | * 270 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 271 | * opcode (which leaves remaining gas untouched) while Solidity uses an 272 | * invalid opcode to revert (consuming all remaining gas). 273 | * 274 | * Requirements: 275 | * - The divisor cannot be zero. 276 | * 277 | * _Available since v2.4.0._ 278 | */ 279 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 280 | require(b != 0, errorMessage); 281 | return a % b; 282 | } 283 | } 284 | 285 | /* 286 | * @dev Provides information about the current execution context, including the 287 | * sender of the transaction and its data. While these are generally available 288 | * via msg.sender and msg.data, they should not be accessed in such a direct 289 | * manner, since when dealing with GSN meta-transactions the account sending and 290 | * paying for execution may not be the actual sender (as far as an application 291 | * is concerned). 292 | * 293 | * This contract is only required for intermediate, library-like contracts. 294 | */ 295 | contract Context { 296 | // Empty internal constructor, to prevent people from mistakenly deploying 297 | // an instance of this contract, which should be used via inheritance. 298 | constructor () internal { } 299 | 300 | function _msgSender() internal view virtual returns (address payable) { 301 | return msg.sender; 302 | } 303 | 304 | function _msgData() internal view virtual returns (bytes memory) { 305 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 306 | return msg.data; 307 | } 308 | } 309 | 310 | /** 311 | * @dev Implementation of the {IERC20} interface. 312 | * 313 | * This implementation is agnostic to the way tokens are created. This means 314 | * that a supply mechanism has to be added in a derived contract using {_mint}. 315 | * For a generic mechanism see {ERC20Mintable}. 316 | * 317 | * TIP: For a detailed writeup see our guide 318 | * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 319 | * to implement supply mechanisms]. 320 | * 321 | * We have followed general OpenZeppelin guidelines: functions revert instead 322 | * of returning `false` on failure. This behavior is nonetheless conventional 323 | * and does not conflict with the expectations of ERC20 applications. 324 | * 325 | * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 326 | * This allows applications to reconstruct the allowance for all accounts just 327 | * by listening to said events. Other implementations of the EIP may not emit 328 | * these events, as it isn't required by the specification. 329 | * 330 | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 331 | * functions have been added to mitigate the well-known issues around setting 332 | * allowances. See {IERC20-approve}. 333 | */ 334 | contract ERC20 is Context, IERC20 { 335 | using SafeMath for uint256; 336 | 337 | mapping (address => uint256) private _balances; 338 | 339 | mapping (address => mapping (address => uint256)) private _allowances; 340 | 341 | uint256 private _totalSupply; 342 | 343 | /** 344 | * @dev See {IERC20-totalSupply}. 345 | */ 346 | function totalSupply() public view override returns (uint256) { 347 | return _totalSupply; 348 | } 349 | 350 | /** 351 | * @dev See {IERC20-balanceOf}. 352 | */ 353 | function balanceOf(address account) public view override returns (uint256) { 354 | return _balances[account]; 355 | } 356 | 357 | /** 358 | * @dev See {IERC20-transfer}. 359 | * 360 | * Requirements: 361 | * 362 | * - `recipient` cannot be the zero address. 363 | * - the caller must have a balance of at least `amount`. 364 | */ 365 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 366 | _transfer(_msgSender(), recipient, amount); 367 | return true; 368 | } 369 | 370 | /** 371 | * @dev See {IERC20-allowance}. 372 | */ 373 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 374 | return _allowances[owner][spender]; 375 | } 376 | 377 | /** 378 | * @dev See {IERC20-approve}. 379 | * 380 | * Requirements: 381 | * 382 | * - `spender` cannot be the zero address. 383 | */ 384 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 385 | _approve(_msgSender(), spender, amount); 386 | return true; 387 | } 388 | 389 | /** 390 | * @dev See {IERC20-transferFrom}. 391 | * 392 | * Emits an {Approval} event indicating the updated allowance. This is not 393 | * required by the EIP. See the note at the beginning of {ERC20}; 394 | * 395 | * Requirements: 396 | * - `sender` and `recipient` cannot be the zero address. 397 | * - `sender` must have a balance of at least `amount`. 398 | * - the caller must have allowance for `sender`'s tokens of at least 399 | * `amount`. 400 | */ 401 | function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 402 | _transfer(sender, recipient, amount); 403 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 404 | return true; 405 | } 406 | 407 | /** 408 | * @dev Atomically increases the allowance granted to `spender` by the caller. 409 | * 410 | * This is an alternative to {approve} that can be used as a mitigation for 411 | * problems described in {IERC20-approve}. 412 | * 413 | * Emits an {Approval} event indicating the updated allowance. 414 | * 415 | * Requirements: 416 | * 417 | * - `spender` cannot be the zero address. 418 | */ 419 | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 420 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 421 | return true; 422 | } 423 | 424 | /** 425 | * @dev Atomically decreases the allowance granted to `spender` by the caller. 426 | * 427 | * This is an alternative to {approve} that can be used as a mitigation for 428 | * problems described in {IERC20-approve}. 429 | * 430 | * Emits an {Approval} event indicating the updated allowance. 431 | * 432 | * Requirements: 433 | * 434 | * - `spender` cannot be the zero address. 435 | * - `spender` must have allowance for the caller of at least 436 | * `subtractedValue`. 437 | */ 438 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 439 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 440 | return true; 441 | } 442 | 443 | /** 444 | * @dev Moves tokens `amount` from `sender` to `recipient`. 445 | * 446 | * This is internal function is equivalent to {transfer}, and can be used to 447 | * e.g. implement automatic token fees, slashing mechanisms, etc. 448 | * 449 | * Emits a {Transfer} event. 450 | * 451 | * Requirements: 452 | * 453 | * - `sender` cannot be the zero address. 454 | * - `recipient` cannot be the zero address. 455 | * - `sender` must have a balance of at least `amount`. 456 | */ 457 | function _transfer(address sender, address recipient, uint256 amount) internal virtual { 458 | require(sender != address(0), "ERC20: transfer from the zero address"); 459 | require(recipient != address(0), "ERC20: transfer to the zero address"); 460 | 461 | _beforeTokenTransfer(sender, recipient, amount); 462 | 463 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 464 | _balances[recipient] = _balances[recipient].add(amount); 465 | emit Transfer(sender, recipient, amount); 466 | } 467 | 468 | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 469 | * the total supply. 470 | * 471 | * Emits a {Transfer} event with `from` set to the zero address. 472 | * 473 | * Requirements 474 | * 475 | * - `to` cannot be the zero address. 476 | */ 477 | function _mint(address account, uint256 amount) internal virtual { 478 | require(account != address(0), "ERC20: mint to the zero address"); 479 | 480 | _beforeTokenTransfer(address(0), account, amount); 481 | 482 | _totalSupply = _totalSupply.add(amount); 483 | _balances[account] = _balances[account].add(amount); 484 | emit Transfer(address(0), account, amount); 485 | } 486 | 487 | /** 488 | * @dev Destroys `amount` tokens from `account`, reducing the 489 | * total supply. 490 | * 491 | * Emits a {Transfer} event with `to` set to the zero address. 492 | * 493 | * Requirements 494 | * 495 | * - `account` cannot be the zero address. 496 | * - `account` must have at least `amount` tokens. 497 | */ 498 | function _burn(address account, uint256 amount) internal virtual { 499 | require(account != address(0), "ERC20: burn from the zero address"); 500 | 501 | _beforeTokenTransfer(account, address(0), amount); 502 | 503 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 504 | _totalSupply = _totalSupply.sub(amount); 505 | emit Transfer(account, address(0), amount); 506 | } 507 | 508 | /** 509 | * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. 510 | * 511 | * This is internal function is equivalent to `approve`, and can be used to 512 | * e.g. set automatic allowances for certain subsystems, etc. 513 | * 514 | * Emits an {Approval} event. 515 | * 516 | * Requirements: 517 | * 518 | * - `owner` cannot be the zero address. 519 | * - `spender` cannot be the zero address. 520 | */ 521 | function _approve(address owner, address spender, uint256 amount) internal virtual { 522 | require(owner != address(0), "ERC20: approve from the zero address"); 523 | require(spender != address(0), "ERC20: approve to the zero address"); 524 | 525 | _allowances[owner][spender] = amount; 526 | emit Approval(owner, spender, amount); 527 | } 528 | 529 | /** 530 | * @dev Destroys `amount` tokens from `account`.`amount` is then deducted 531 | * from the caller's allowance. 532 | * 533 | * See {_burn} and {_approve}. 534 | */ 535 | function _burnFrom(address account, uint256 amount) internal virtual { 536 | _burn(account, amount); 537 | _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); 538 | } 539 | 540 | /** 541 | * @dev Hook that is called before any transfer of tokens. This includes 542 | * minting and burning. 543 | * 544 | * Calling conditions: 545 | * 546 | * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens 547 | * will be to transferred to `to`. 548 | * - when `from` is zero, `amount` tokens will be minted for `to`. 549 | * - when `to` is zero, `amount` of `from`'s tokens will be burned. 550 | * - `from` and `to` are never both zero. 551 | * 552 | * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. 553 | */ 554 | function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 555 | } 556 | 557 | /** 558 | * @dev Contract module which provides a basic access control mechanism, where 559 | * there is an account (an owner) that can be granted exclusive access to 560 | * specific functions. 561 | * 562 | * This module is used through inheritance. It will make available the modifier 563 | * `onlyOwner`, which can be applied to your functions to restrict their use to 564 | * the owner. 565 | */ 566 | contract Ownable is Context { 567 | address private _owner; 568 | 569 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 570 | 571 | /** 572 | * @dev Initializes the contract setting the deployer as the initial owner. 573 | */ 574 | constructor () internal { 575 | address msgSender = _msgSender(); 576 | _owner = msgSender; 577 | emit OwnershipTransferred(address(0), msgSender); 578 | } 579 | 580 | /** 581 | * @dev Returns the address of the current owner. 582 | */ 583 | function owner() public view returns (address) { 584 | return _owner; 585 | } 586 | 587 | /** 588 | * @dev Throws if called by any account other than the owner. 589 | */ 590 | modifier onlyOwner() { 591 | require(isOwner(), "Ownable: caller is not the owner"); 592 | _; 593 | } 594 | 595 | /** 596 | * @dev Returns true if the caller is the current owner. 597 | */ 598 | function isOwner() public view returns (bool) { 599 | return _msgSender() == _owner; 600 | } 601 | 602 | /** 603 | * @dev Leaves the contract without owner. It will not be possible to call 604 | * `onlyOwner` functions anymore. Can only be called by the current owner. 605 | * 606 | * NOTE: Renouncing ownership will leave the contract without an owner, 607 | * thereby removing any functionality that is only available to the owner. 608 | */ 609 | function renounceOwnership() public virtual onlyOwner { 610 | emit OwnershipTransferred(_owner, address(0)); 611 | _owner = address(0); 612 | } 613 | 614 | /** 615 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 616 | * Can only be called by the current owner. 617 | */ 618 | function transferOwnership(address newOwner) public virtual onlyOwner { 619 | _transferOwnership(newOwner); 620 | } 621 | 622 | /** 623 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 624 | */ 625 | function _transferOwnership(address newOwner) internal virtual { 626 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 627 | emit OwnershipTransferred(_owner, newOwner); 628 | _owner = newOwner; 629 | } 630 | } 631 | 632 | /** 633 | * This smart contract code is Copyright 2020 WEMADETREE Ltd. For more information see https://wemixnetwork.com/ 634 | * 635 | * Everything follows openzeppelin-solidity's ERC20 and libraries code except for this token mining every block 636 | */ 637 | 638 | contract WemixToken is ERC20, ERC20Detailed, Ownable{ 639 | uint256 public unitStaking = 2000000 ether; //Unit of single staking 640 | uint256 public minBlockWaitingWithdrawal = 7776000; //Minimum number of blocks to wait for withdrawal after staking 641 | //about 90 days (Assumes 1 block per second) 642 | address public ecoFund; // Wemix Ecosystem fund address to receive a minted token 643 | address public wemix; // Use for continuous development and maintenance of WEMIX 644 | 645 | struct Partner { 646 | uint256 serial; //unique number of registered partner 647 | address partner; //address to receive a minted token 648 | address payer; //address paid token when staking 649 | uint256 blockStaking; //block number when staking 650 | uint256 blockWaitingWithdrawal; // blocks to wait for withdrawal 651 | uint256 balanceStaking; // tokens deposited when staking 652 | } 653 | Partner[] public allPartners; 654 | mapping(uint256 => uint256) private allPartnersIndex; //Partner.serial => index of allPartners 655 | uint256 private _nextSerial = 1; //serial number to be given to next partner 656 | mapping (address => bool) public allowedPartners; //address of partner allowed to staking 657 | 658 | uint256 public nextPartnerToMint; //index of allPartners to receive minted token in next block 659 | 660 | uint256 public blockUnitForMint = 60; //block unit for minting 661 | uint256 public mintToPartner = 0.5 ether; //balance be minted to block-partner per block 662 | uint256 public mintToEcoFund = 0.25 ether; //balance be minted to eco-fund per block 663 | uint256 public mintToWemix = 0.25 ether; //balance be minted to wenix per block 664 | 665 | uint256 public blockToMint = 0; //the next mintable block 666 | uint256 private nextBlockUnitForMint; //if it is changed to greater than 0, then mint() is executed, blockToMint is updated to it and it is initialized to 0. 667 | 668 | event Staked(address indexed partner, address indexed payer, uint256 indexed serial); 669 | event Withdrawal(address indexed partner, address indexed payer, uint256 indexed serial); 670 | 671 | constructor(address _ecoFund, address _wemix) 672 | ERC20Detailed("WEMIX TOKEN", "WEMIX", 18) public { 673 | super._mint(_msgSender(), 1000000000*10**18); 674 | ecoFund = _ecoFund; 675 | wemix = _wemix; 676 | blockToMint = block.number.add(blockUnitForMint); 677 | } 678 | 679 | //Method to register msg.sender as partner 680 | function stake(uint256 _withdrawalWaitingMinBlock) public { 681 | _stake(_msgSender(), _withdrawalWaitingMinBlock); 682 | } 683 | 684 | //Method to register the other address as a partner. 685 | //msg.sender becomes a payer and the payer has the authority of withdrawal. 686 | function stakeDelegated(address _partner, uint256 _withdrawalWaitingMinBlock) public { 687 | _stake(_partner, _withdrawalWaitingMinBlock); 688 | } 689 | 690 | function _stake(address _partner, uint256 _blockWaitingWithdrawal) private { 691 | require(_partner != address(0), "WemixToken: _partner is the zero address"); 692 | //only pre-approved addresses are allowed 693 | require(allowedPartners[_partner] == true, "WemixToken: only pre-approved addresses are allowed"); 694 | allowedPartners[_partner] = false; 695 | 696 | //if _blockWaitingWithdrawal is lower than the minimum, adjust it to the minimum. 697 | if(_blockWaitingWithdrawal < minBlockWaitingWithdrawal) { 698 | _blockWaitingWithdrawal = minBlockWaitingWithdrawal; 699 | } 700 | 701 | //send msg.serder's token to this contract, 702 | super.transfer(address(this), unitStaking); 703 | 704 | //make block-partner 705 | allPartners.push(Partner({ 706 | serial : _nextSerial, 707 | partner : _partner, 708 | payer : _msgSender(), 709 | blockStaking: block.number, 710 | blockWaitingWithdrawal : _blockWaitingWithdrawal, 711 | balanceStaking : unitStaking 712 | })); 713 | allPartnersIndex[_nextSerial] = allPartners.length.sub(1); 714 | 715 | emit Staked(_partner, _msgSender(), _nextSerial); 716 | 717 | _nextSerial = _nextSerial.add(1); 718 | } 719 | 720 | //withdraw the staking token. 721 | function withdraw(uint256 _serial) public { 722 | uint256 _subIndex = allPartnersIndex[_serial]; 723 | require(_subIndex < allPartners.length, "WemixToken: _subIndex equal or higher than allPartners.length"); 724 | 725 | Partner memory _p = allPartners[_subIndex]; 726 | require(_p.serial == _serial, "WemixToken: _p.serial is different with _serial"); 727 | 728 | //only payer can withdraw 729 | require(_p.payer == _msgSender(), "WemixToken: _p.payer is different with _msgSender()"); 730 | //check if the withdrawal wait block has passed, 731 | require(_p.blockStaking + _p.blockWaitingWithdrawal <= block.number, "WemixToken: _p.blockStaking + _p.blockWaitingWithdrawal is higher than block.number"); 732 | //send staking token to the payer, 733 | super._transfer(address(this), _p.payer, _p.balanceStaking); 734 | 735 | emit Withdrawal(_p.partner, _p.payer, _serial); 736 | 737 | //remove a partner from allPartners. 738 | uint256 _lastIndex = allPartners.length.sub(1); 739 | if(_subIndex != _lastIndex) { 740 | Partner memory _lastP = allPartners[_lastIndex]; 741 | allPartners[_subIndex] = _lastP; 742 | allPartnersIndex[_lastP.serial] = _subIndex; 743 | } 744 | allPartners.pop(); 745 | allPartnersIndex[_serial] = 0; 746 | } 747 | 748 | //mint tokens 749 | function mint() public { 750 | require(isMintable(), "WemixToken: blockToMint is higher than block.number"); 751 | 752 | if (allPartners.length > 0) { 753 | if(nextPartnerToMint >= allPartners.length){ 754 | nextPartnerToMint = 0; 755 | } 756 | super._mint(allPartners[nextPartnerToMint].partner, mintToPartner.mul(blockUnitForMint)); 757 | super._mint(wemix, mintToWemix.mul(blockUnitForMint)); 758 | super._mint(ecoFund, mintToEcoFund.mul(blockUnitForMint)); 759 | nextPartnerToMint = nextPartnerToMint.add(1); 760 | } 761 | 762 | if(nextBlockUnitForMint > 0) { 763 | blockUnitForMint = nextBlockUnitForMint; 764 | nextBlockUnitForMint = 0; 765 | } 766 | blockToMint = blockToMint.add(blockUnitForMint); 767 | } 768 | 769 | function addAllowedPartner(address _account) public onlyOwner { 770 | require(_account != address(0), "WemixToken: _account is the zero address"); 771 | allowedPartners[_account] = true; 772 | } 773 | 774 | function removeAllowedPartner(address _account) public onlyOwner { 775 | allowedPartners[_account] = false; 776 | } 777 | 778 | function partnersNumber() public view returns (uint) { 779 | return allPartners.length; 780 | } 781 | 782 | function partnerBySerial(uint _serial) public view returns (uint256 serial, address partner, address payer, uint blockStaking, uint blockWaitingWithdrawal, uint balanceStaking) { 783 | return partnerByIndex(allPartnersIndex[_serial]); 784 | } 785 | 786 | function partnerByIndex(uint _index) public view returns (uint256 serial, address partner, address payer, uint blockStaking, uint blockWaitingWithdrawal, uint balanceStaking) { 787 | require(_index < allPartners.length, "WemixToken: _index is equal or higher than allPartners.length"); 788 | 789 | Partner memory _p = allPartners[_index]; 790 | 791 | serial = _p.serial; 792 | partner = _p.partner; 793 | payer = _p.payer; 794 | blockStaking = _p.blockStaking; 795 | blockWaitingWithdrawal = _p.blockWaitingWithdrawal; 796 | balanceStaking = _p.balanceStaking; 797 | } 798 | 799 | function isMintable() public view returns(bool) { 800 | return (block.number >= blockToMint); 801 | } 802 | 803 | function change_ecoFund(address _account) public onlyOwner{ 804 | require(_account != address(0), "WemixToken: _account is the zero address"); 805 | ecoFund = _account; 806 | } 807 | 808 | function change_wemix(address _account) public onlyOwner{ 809 | require(_account != address(0), "WemixToken: _account is the zero address"); 810 | wemix = _account; 811 | } 812 | 813 | function change_minBlockWaitingWithdrawal(uint256 _block) public onlyOwner{ 814 | minBlockWaitingWithdrawal = _block; 815 | } 816 | 817 | function change_unitStaking(uint256 _unit) public onlyOwner{ 818 | unitStaking = _unit; 819 | } 820 | 821 | function change_mintToPartner(uint256 _value) public onlyOwner { 822 | mintToPartner = _value; 823 | } 824 | 825 | function change_mintToWemix(uint256 _value) public onlyOwner { 826 | mintToWemix = _value; 827 | } 828 | 829 | function change_mintToEcoFund(uint256 _value) public onlyOwner { 830 | mintToEcoFund = _value; 831 | } 832 | 833 | function change_blockUnitForMint(uint256 _block) public onlyOwner { 834 | nextBlockUnitForMint = _block; 835 | } 836 | } 837 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/wemade-tree/wemix-token 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ethereum/go-ethereum v1.9.15 // indirect 7 | github.com/stretchr/testify v1.7.0 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= 2 | github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= 3 | github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= 4 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 5 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 6 | github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= 7 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 8 | github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= 9 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 10 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 11 | github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= 12 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 13 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 14 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 15 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 16 | github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= 17 | github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= 18 | github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= 19 | github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= 20 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 21 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 22 | github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= 23 | github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= 24 | github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= 25 | github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 26 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 27 | github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= 28 | github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= 29 | github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= 30 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 31 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 32 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 33 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 34 | github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= 35 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 36 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 37 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 38 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 39 | github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= 40 | github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= 41 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 42 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 43 | github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 44 | github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 45 | github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 46 | github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM= 47 | github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 48 | github.com/ethereum/go-ethereum v1.9.15 h1:wrWl+QrtutRUJ9LZXdUqBoGoo2b1tOCYRDrAOQhCY3A= 49 | github.com/ethereum/go-ethereum v1.9.15/go.mod h1:slT8bPPRhXsyNTwHQxrOnjuTZ1sDXRajW11EkJ84QJ0= 50 | github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 51 | github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= 52 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 53 | github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= 54 | github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= 55 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 56 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 57 | github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= 58 | github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= 59 | github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= 60 | github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= 61 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 62 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 63 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 64 | github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c h1:zqAKixg3cTcIasAMJV+EcfVbWwLpOZ7LeoWJvcuD/5Q= 65 | github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 66 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 67 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 68 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 69 | github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989 h1:giknQ4mEuDFmmHSrGcbargOuLHQGtywqo4mheITex54= 70 | github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 71 | github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= 72 | github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= 73 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 74 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 75 | github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= 76 | github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= 77 | github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= 78 | github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= 79 | github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= 80 | github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= 81 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 82 | github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 83 | github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw= 84 | github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= 85 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 86 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 87 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 88 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 89 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 90 | github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 91 | github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 92 | github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 93 | github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 94 | github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 95 | github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= 96 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 97 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 98 | github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= 99 | github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= 100 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 101 | github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 102 | github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk= 103 | github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 104 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 105 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 106 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 107 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 108 | github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= 109 | github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= 110 | github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= 111 | github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= 112 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 113 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 114 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 115 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 116 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 117 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 118 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 119 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 120 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 121 | github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150 h1:ZeU+auZj1iNzN8iVhff6M38Mfu73FQiJve/GEXYJBjE= 122 | github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 123 | github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= 124 | github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= 125 | github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= 126 | github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= 127 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 128 | github.com/shirou/gopsutil v2.20.5-0.20200531151128-663af789c085+incompatible h1:+gAR1bMhuoQnZMTWFIvp7ukynULPsteLzG+siZKLtD8= 129 | github.com/shirou/gopsutil v2.20.5-0.20200531151128-663af789c085+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 130 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 131 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 132 | github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= 133 | github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= 134 | github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= 135 | github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= 136 | github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= 137 | github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= 138 | github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= 139 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 140 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 141 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 142 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 143 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 144 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 145 | github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= 146 | github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= 147 | github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= 148 | github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= 149 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 150 | github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= 151 | github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= 152 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 153 | golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= 154 | golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 155 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 156 | golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 157 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 158 | golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U= 159 | golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 160 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 161 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 162 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 163 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 164 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 165 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 166 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= 167 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 168 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 169 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 170 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 171 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 172 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 173 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 174 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 175 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 176 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 177 | gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 178 | gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= 179 | gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200603215123-a4a8cb9d2cbc/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= 180 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 181 | gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= 182 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 183 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 184 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 185 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 186 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 187 | -------------------------------------------------------------------------------- /test/WemixToken_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "math/big" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | 10 | "github.com/ethereum/go-ethereum/common" 11 | "github.com/ethereum/go-ethereum/core/types" 12 | "github.com/ethereum/go-ethereum/crypto" 13 | "github.com/wemade-tree/wemix-token/backend" 14 | ) 15 | 16 | type ( 17 | //Structure to store block partner information 18 | typePartner struct { 19 | Serial *big.Int 20 | Partner common.Address 21 | Payer common.Address 22 | BlockStaking *big.Int 23 | BlockWaitingWithdrawal *big.Int 24 | BalanceStaking *big.Int 25 | } 26 | typePartnerSlice []*typePartner 27 | ) 28 | 29 | //Print all block partner information in log. 30 | func (p *typePartner) log(serial *big.Int, t *testing.T) { 31 | t.Logf("Partner:%s serial:%v", p.Partner.Hex(), serial) 32 | t.Logf(" -Payer:%v", p.Payer.Hex()) 33 | t.Logf(" -BalanceStaking:%v", p.BalanceStaking) 34 | t.Logf(" -BlockStaking:%v", p.BlockStaking) 35 | t.Logf(" -BlockWaitingWithdrawal:%v", p.BlockWaitingWithdrawal) 36 | } 37 | 38 | //Retrieve and store all block partner information from the blockchain, 39 | func (p *typePartnerSlice) loadAllStake(t *testing.T, contract *backend.Contract) { 40 | partnersNumber := (*big.Int)(nil) 41 | assert.NoError(t, contract.Call(&partnersNumber, "partnersNumber")) 42 | 43 | for i := int64(0); i < partnersNumber.Int64(); i++ { 44 | s := typePartner{} 45 | assert.NoError(t, contract.Call(&s, "partnerByIndex", new(big.Int).SetInt64(i))) 46 | *p = append(*p, &s) 47 | } 48 | t.Logf("ok > loadAllStake, partners number: %d", partnersNumber) 49 | } 50 | 51 | //After compiling and distributing the contract, return the Contract pointer object. 52 | func depolyWemix(t *testing.T) *backend.Contract { 53 | contract, err := backend.NewContract("../contracts/WemixToken.sol", "WemixToken") 54 | assert.NoError(t, err) 55 | 56 | ecoFundKey, _ := crypto.GenerateKey() 57 | wemixKey, _ := crypto.GenerateKey() 58 | 59 | //deploy contract 60 | args := []interface{}{ 61 | crypto.PubkeyToAddress(ecoFundKey.PublicKey), //ecoFund address 62 | crypto.PubkeyToAddress(wemixKey.PublicKey), //wemix address 63 | } 64 | if err := contract.Deploy(args...); err != nil { 65 | assert.NoError(t, err) 66 | } 67 | return contract 68 | } 69 | 70 | type Contract struct { 71 | Code string `json:"code"` 72 | RCode string `json:"runtime-code"` 73 | Info ContractInfo `json:"info"` 74 | } 75 | 76 | type ContractInfo struct { 77 | Source string `json:"source"` 78 | Language string `json:"language"` 79 | LanguageVersion string `json:"languageVersion"` 80 | CompilerVersion string `json:"compilerVersion"` 81 | CompilerOptions string `json:"compilerOptions"` 82 | AbiDefinition interface{} `json:"abiDefinition"` 83 | UserDoc interface{} `json:"userDoc"` 84 | DeveloperDoc interface{} `json:"developerDoc"` 85 | Metadata string `json:"metadata"` 86 | } 87 | 88 | //Test to compile and deploy the contract 89 | func TestWemixDeploy(t *testing.T) { 90 | contract := depolyWemix(t) 91 | 92 | // jsonContract := &Contract{ 93 | // Code: hexutil.Encode(contract.Code), 94 | // RCode: hexutil.Encode(contract.Code), 95 | // Info: ContractInfo{ 96 | // Source: contract.Info.Source, 97 | // Language: contract.Info.Language, 98 | // LanguageVersion: contract.Info.LanguageVersion, 99 | // CompilerVersion: contract.Info.CompilerVersion, 100 | // CompilerOptions: contract.Info.CompilerOptions, 101 | // AbiDefinition: contract.Info.AbiDefinition, 102 | // UserDoc: contract.Info.UserDoc, 103 | // DeveloperDoc: contract.Info.DeveloperDoc, 104 | // Metadata: contract.Info.Metadata, 105 | // }, 106 | // } 107 | 108 | // b, err := json.Marshal(jsonContract) 109 | // assert.NoError(t, err) 110 | 111 | // var buff bytes.Buffer 112 | // gz := gzip.NewWriter(&buff) 113 | // _, err = gz.Write(b) 114 | // assert.NoError(t, err) 115 | 116 | // assert.NoError(t, gz.Close()) 117 | // t.Log(hexutil.Encode(b)) 118 | 119 | // wemix := (*backend.Contract)(nil) 120 | // if err := json.Unmarshal(b, &wemix); err != nil { 121 | // assert.NoError(t, err) 122 | // } 123 | // contract = wemix 124 | 125 | t.Log("contract source file:", contract.File) 126 | t.Log("contract name:", contract.Name) 127 | t.Log("contract Language:", contract.Info.Language) 128 | t.Log("contract LanguageVersion", contract.Info.LanguageVersion) 129 | t.Log("contract CompilerVersion", contract.Info.CompilerVersion) 130 | t.Log("contract bytecode size:", len(contract.Code)) 131 | 132 | t.Log("ok > contract address deployed", contract.Address.Hex()) 133 | 134 | // t.Log("contract bytecode:", hexutil.Encode(contract.Code)) 135 | // abiBytes, _ := json.Marshal(contract.Info.AbiDefinition) 136 | // t.Log("contract abi:", string(abiBytes)) 137 | 138 | } 139 | 140 | //Test to verify the variables of the deployed contract. 141 | //Fatal if the expected value and the actual contract value differ. 142 | func TestWemixVariable(t *testing.T) { 143 | contract := depolyWemix(t) 144 | block := contract.Backend.Blockchain().CurrentBlock().Header().Number 145 | 146 | checkVariable(t, contract, "name", "WEMIX TOKEN") 147 | checkVariable(t, contract, "symbol", "WEMIX") 148 | checkVariable(t, contract, "decimals", uint8(18)) 149 | checkVariable(t, contract, "totalSupply", toBig(t, "1000000000000000000000000000")) 150 | checkVariable(t, contract, "unitStaking", toBig(t, "2000000000000000000000000")) 151 | checkVariable(t, contract, "minBlockWaitingWithdrawal", new(big.Int).SetUint64(7776000)) 152 | checkVariable(t, contract, "blockUnitForMint", new(big.Int).SetUint64(60)) 153 | checkVariable(t, contract, "ecoFund", contract.ConstructorInputs[0].(common.Address)) 154 | checkVariable(t, contract, "wemix", contract.ConstructorInputs[1].(common.Address)) 155 | checkVariable(t, contract, "nextPartnerToMint", new(big.Int)) 156 | checkVariable(t, contract, "mintToPartner", new(big.Int).SetUint64(500000000000000000)) 157 | checkVariable(t, contract, "mintToEcoFund", new(big.Int).SetUint64(250000000000000000)) 158 | checkVariable(t, contract, "mintToWemix", new(big.Int).SetUint64(250000000000000000)) 159 | checkVariable(t, contract, "blockToMint", new(big.Int).Add(block, new(big.Int).SetUint64(60))) 160 | } 161 | 162 | //Test to execute onlyOwner modifier method. 163 | func TestWemixExecute(t *testing.T) { 164 | contract := depolyWemix(t) 165 | 166 | executeChangeMethod(t, contract, "unitStaking", big.NewInt(1)) 167 | executeChangeMethod(t, contract, "minBlockWaitingWithdrawal", big.NewInt(1)) 168 | executeChangeMethod(t, contract, "ecoFund", common.HexToAddress("0x0000000000000000000000000000000000000001")) 169 | executeChangeMethod(t, contract, "wemix", common.HexToAddress("0x0000000000000000000000000000000000000001")) 170 | executeChangeMethod(t, contract, "mintToPartner", big.NewInt(1)) 171 | executeChangeMethod(t, contract, "mintToEcoFund", big.NewInt(1)) 172 | executeChangeMethod(t, contract, "mintToWemix", big.NewInt(1)) 173 | } 174 | 175 | //test to run onlyOwner modifier method under non-owner account. 176 | func TestWemixOwner(t *testing.T) { 177 | contract := depolyWemix(t) 178 | 179 | key, _ := crypto.GenerateKey() 180 | 181 | expectedFail(t, contract, key, "change_unitStaking", big.NewInt(1)) 182 | expectedFail(t, contract, key, "change_minBlockWaitingWithdrawal", big.NewInt(1)) 183 | expectedFail(t, contract, key, "change_ecoFund", common.HexToAddress("0x0000000000000000000000000000000000000001")) 184 | expectedFail(t, contract, key, "change_wemix", common.HexToAddress("0x0000000000000000000000000000000000000002")) 185 | expectedFail(t, contract, key, "change_mintToPartner", big.NewInt(1)) 186 | expectedFail(t, contract, key, "change_mintToWemix", big.NewInt(1)) 187 | expectedFail(t, contract, key, "transferOwnership", func() common.Address { 188 | k, _ := crypto.GenerateKey() 189 | return crypto.PubkeyToAddress(k.PublicKey) 190 | }()) 191 | 192 | newOwnerKey, _ := crypto.GenerateKey() 193 | expectedSuccess(t, contract, nil, "transferOwnership", crypto.PubkeyToAddress(newOwnerKey.PublicKey)) 194 | expectedSuccess(t, contract, newOwnerKey, "transferOwnership", contract.Owner) 195 | } 196 | 197 | //Test to run addAllowedStaker method. 198 | func TestWemixAllowedPartner(t *testing.T) { 199 | contract := depolyWemix(t) 200 | 201 | //make an error occur 202 | r, err := contract.Execute(nil, "stake", new(big.Int)) 203 | assert.NoError(t, err) 204 | assert.True(t, r.Status == 0) 205 | 206 | //make partner 207 | partnerKey, _ := crypto.GenerateKey() 208 | partner := crypto.PubkeyToAddress(partnerKey.PublicKey) 209 | 210 | //addAllowedPartner 211 | r, err = contract.Execute(nil, "addAllowedPartner", partner) 212 | assert.NoError(t, err) 213 | assert.True(t, r.Status == 1) 214 | 215 | topics := []common.Hash{} 216 | r, err = contract.Execute(nil, "stakeDelegated", partner, new(big.Int)) 217 | assert.NoError(t, err) 218 | assert.True(t, r.Status == 1) 219 | for _, g := range r.Logs { 220 | if g.Topics[0] == contract.Abi.Events["Staked"].ID { 221 | topics = append(topics, g.Topics...) 222 | } 223 | } 224 | assert.Equal(t, common.BytesToAddress(topics[1].Bytes()), partner) 225 | assert.Equal(t, common.BytesToAddress(topics[2].Bytes()), contract.Owner) 226 | 227 | t.Log("ok > test addAllowedPartner") 228 | } 229 | 230 | //test staking 231 | func TestWemixStake(t *testing.T) { 232 | contract := depolyWemix(t) 233 | 234 | testStake(t, contract, false) 235 | } 236 | 237 | func testStake(t *testing.T, contract *backend.Contract, showStakeInfo bool) typeKeyMap { 238 | unitStaking := func() *big.Int { 239 | ret := (*big.Int)(nil) 240 | assert.NoError(t, contract.Call(&ret, "unitStaking")) 241 | return ret 242 | }() 243 | 244 | minBlockWaitingWithdrawal := (*big.Int)(nil) 245 | assert.NoError(t, contract.Call(&minBlockWaitingWithdrawal, "minBlockWaitingWithdrawal")) 246 | 247 | countExecuteStake := int64(0) 248 | partnerKeyMap := typeKeyMap{} 249 | 250 | _stake := func(delegation bool, partner common.Address, payerKey *ecdsa.PrivateKey, waitBlock *big.Int) *typePartner { 251 | var r *types.Receipt 252 | var err error 253 | //addAllowedPartner 254 | r, err = contract.Execute(nil, "addAllowedPartner", partner) 255 | assert.NoError(t, err) 256 | assert.True(t, r.Status == 1) 257 | 258 | if delegation == true { 259 | r, err = contract.Execute(payerKey, "stakeDelegated", partner, waitBlock) 260 | } else { 261 | r, err = contract.Execute(payerKey, "stake", waitBlock) 262 | } 263 | assert.NoError(t, err) 264 | assert.True(t, r.Status == 1) 265 | 266 | serial := (*big.Int)(nil) 267 | for _, g := range r.Logs { 268 | if g.Topics[0] == contract.Abi.Events["Staked"].ID { 269 | serial = g.Topics[3].Big() 270 | } 271 | } 272 | assert.NotNil(t, serial) 273 | countExecuteStake++ 274 | 275 | result := typePartner{} 276 | assert.NoError(t, contract.Call(&result, "partnerBySerial", serial)) 277 | if showStakeInfo == true { 278 | result.log(serial, t) 279 | } 280 | return &result 281 | } 282 | 283 | makePartner := func() (common.Address, *ecdsa.PrivateKey) { 284 | partnerKey, _ := crypto.GenerateKey() 285 | partner := crypto.PubkeyToAddress(partnerKey.PublicKey) 286 | partnerKeyMap[partner] = partnerKey 287 | return partner, partnerKey 288 | } 289 | 290 | //stake 291 | for i := 0; i < 3; i++ { 292 | partner, partnerKey := makePartner() 293 | 294 | //send wemix for testing, 295 | amount := new(big.Int).Mul(unitStaking, new(big.Int).SetInt64(int64(i+1))) 296 | r, err := contract.Execute(nil, "transfer", partner, amount) 297 | assert.NoError(t, err) 298 | assert.True(t, r.Status == 1) 299 | waitBlock := new(big.Int).Mul(minBlockWaitingWithdrawal, new(big.Int).SetInt64(int64(i+1))) 300 | 301 | for { 302 | result := _stake(false, partner, partnerKey, waitBlock) 303 | 304 | assert.Equal(t, result.Payer, result.Partner) 305 | assert.Equal(t, partner, result.Payer) 306 | 307 | //when all tokens received have been exhausted, terminate staking. 308 | balance := (*big.Int)(nil) 309 | assert.NoError(t, contract.Call(&balance, "balanceOf", partner)) 310 | if balance.Sign() == 0 { 311 | break 312 | } 313 | } 314 | } 315 | 316 | //delegated stake 317 | for i := 0; i < 5; i++ { 318 | partner, _ := makePartner() 319 | 320 | amount := new(big.Int).Mul(unitStaking, new(big.Int).SetInt64(int64(i+1))) 321 | 322 | waitBlock := new(big.Int).Mul(minBlockWaitingWithdrawal, new(big.Int).SetInt64(int64(i+1))) 323 | 324 | for { 325 | result := _stake(true, partner, contract.OwnerKey, waitBlock) 326 | 327 | assert.NotEqual(t, result.Payer, result.Partner) 328 | assert.Equal(t, contract.Owner, result.Payer) 329 | 330 | amount = new(big.Int).Sub(amount, result.BalanceStaking) 331 | if amount.Sign() == 0 { 332 | break 333 | } 334 | } 335 | } 336 | 337 | //Compare the number of block partners registered with the number registered on the blockchain. 338 | partnersNumber := (*big.Int)(nil) 339 | assert.NoError(t, contract.Call(&partnersNumber, "partnersNumber")) 340 | assert.True(t, partnersNumber.Cmp(new(big.Int).SetInt64(countExecuteStake)) == 0) 341 | 342 | return partnerKeyMap 343 | } 344 | 345 | //test to withdraw 346 | func TestWemixWithdraw(t *testing.T) { 347 | contract := depolyWemix(t) 348 | 349 | //change withdrawalWaitingMinBlockd short for testing. 350 | r, err := contract.Execute(nil, "change_minBlockWaitingWithdrawal", new(big.Int).SetUint64(1000)) 351 | assert.NoError(t, err) 352 | assert.True(t, r.Status == 1) 353 | 354 | partnerKeyMap := testStake(t, contract, false) 355 | 356 | stakes := typePartnerSlice{} 357 | stakes.loadAllStake(t, contract) 358 | 359 | contractBalance := (*big.Int)(nil) 360 | assert.NoError(t, contract.Call(&contractBalance, "balanceOf", contract.Address)) 361 | 362 | totalStakeBalance := new(big.Int) 363 | for i := 0; i < len(stakes); i++ { 364 | totalStakeBalance.Add(totalStakeBalance, stakes[i].BalanceStaking) 365 | } 366 | 367 | assert.True(t, totalStakeBalance.Cmp(contractBalance) == 0) 368 | t.Logf("ok > contract's balance: %v, total stake balance:%v", contractBalance, totalStakeBalance) 369 | 370 | for { 371 | for i, s := range stakes { 372 | key := (*ecdsa.PrivateKey)(nil) 373 | if s.Partner == s.Payer { 374 | key = partnerKeyMap[s.Payer] 375 | } 376 | 377 | r, err := contract.Execute(key, "withdraw", s.Serial) 378 | assert.NoError(t, err) 379 | 380 | block := contract.Backend.Blockchain().CurrentBlock().Header().Number 381 | blockWithdrawable := new(big.Int).Add(s.BlockStaking, s.BlockWaitingWithdrawal) 382 | if r.Status == 1 { 383 | assert.True(t, block.Cmp(blockWithdrawable) >= 0) 384 | t.Logf("ok > withdrawal : %v", s.Serial) 385 | stakes[i] = stakes[len(stakes)-1] 386 | stakes = stakes[:len(stakes)-1] 387 | break 388 | } else { 389 | assert.True(t, block.Cmp(blockWithdrawable) < 0) 390 | } 391 | } 392 | 393 | if len(stakes) == 0 { 394 | break 395 | } 396 | 397 | //make block 398 | contract.Backend.Commit() 399 | } 400 | 401 | for staker, key := range partnerKeyMap { 402 | balance := (*big.Int)(nil) 403 | assert.NoError(t, contract.Call(&balance, "balanceOf", staker)) 404 | if balance.Sign() > 0 { 405 | r, err := contract.Execute(key, "transfer", contract.Owner, balance) 406 | assert.NoError(t, err) 407 | assert.True(t, r.Status == 1) 408 | t.Log("ok > return token to owner") 409 | } 410 | } 411 | } 412 | 413 | func testMint(t *testing.T, contract *backend.Contract) { 414 | stakes := typePartnerSlice{} 415 | stakes.loadAllStake(t, contract) 416 | 417 | balancePartners := func() map[common.Address]*big.Int { 418 | m := make(map[common.Address]*big.Int) 419 | for _, s := range stakes { 420 | if _, ok := m[s.Partner]; ok == true { 421 | continue 422 | } 423 | b := (*big.Int)(nil) 424 | assert.NoError(t, contract.Call(&b, "balanceOf", s.Partner)) 425 | m[s.Partner] = b 426 | } 427 | return m 428 | }() 429 | 430 | wemix := common.Address{} 431 | assert.NoError(t, contract.Call(&wemix, "wemix")) 432 | 433 | balanceWemix := func() *big.Int { 434 | b := (*big.Int)(nil) 435 | assert.NoError(t, contract.Call(&b, "balanceOf", wemix)) 436 | return b 437 | }() 438 | 439 | ecoFund := common.Address{} 440 | assert.NoError(t, contract.Call(&ecoFund, "ecoFund")) 441 | 442 | balanceEcoFund := func() *big.Int { 443 | b := (*big.Int)(nil) 444 | assert.NoError(t, contract.Call(&b, "balanceOf", ecoFund)) 445 | return b 446 | }() 447 | 448 | mintToPartner := (*big.Int)(nil) 449 | assert.NoError(t, contract.Call(&mintToPartner, "mintToPartner")) 450 | 451 | mintToWemix := (*big.Int)(nil) 452 | assert.NoError(t, contract.Call(&mintToWemix, "mintToWemix")) 453 | 454 | mintToEcoFund := (*big.Int)(nil) 455 | assert.NoError(t, contract.Call(&mintToEcoFund, "mintToEcoFund")) 456 | 457 | nextPartnerToMint := (*big.Int)(nil) 458 | assert.NoError(t, contract.Call(&nextPartnerToMint, "nextPartnerToMint")) 459 | 460 | blockUnitForMint := (*big.Int)(nil) 461 | assert.NoError(t, contract.Call(&blockUnitForMint, "blockUnitForMint")) 462 | 463 | indexNext := int(nextPartnerToMint.Uint64()) 464 | totalMinted := new(big.Int) 465 | countExpectedBalance := func() { 466 | if len(stakes) == 0 { 467 | return 468 | } 469 | 470 | if indexNext >= len(stakes) { 471 | indexNext = 0 472 | } 473 | 474 | s := stakes[indexNext] 475 | balancePartners[s.Partner].Add(balancePartners[s.Partner], new(big.Int).Mul(mintToPartner, blockUnitForMint)) 476 | totalMinted.Add(totalMinted, new(big.Int).Mul(mintToPartner, blockUnitForMint)) 477 | indexNext++ 478 | 479 | balanceWemix.Add(balanceWemix, new(big.Int).Mul(mintToWemix, blockUnitForMint)) 480 | totalMinted.Add(totalMinted, new(big.Int).Mul(mintToWemix, blockUnitForMint)) 481 | balanceEcoFund.Add(balanceEcoFund, new(big.Int).Mul(mintToEcoFund, blockUnitForMint)) 482 | totalMinted.Add(totalMinted, new(big.Int).Mul(mintToEcoFund, blockUnitForMint)) 483 | } 484 | 485 | initialTotalSupply := (*big.Int)(nil) 486 | assert.NoError(t, contract.Call(&initialTotalSupply, "totalSupply")) 487 | 488 | startBlock := (*big.Int)(nil) 489 | assert.NoError(t, contract.Call(&startBlock, "blockToMint")) 490 | 491 | timesMinting := uint64(210) 492 | 493 | for i := uint64(0); i < timesMinting; i++ { 494 | blockToMint := (*big.Int)(nil) 495 | assert.NoError(t, contract.Call(&blockToMint, "blockToMint")) 496 | 497 | currentBlock := contract.Backend.Blockchain().CurrentBlock().Header().Number 498 | if currentBlock.Cmp(blockToMint) < 0 { 499 | commitCnt := new(big.Int).Sub(blockToMint, contract.Backend.Blockchain().CurrentBlock().Header().Number) 500 | 501 | for b := uint64(0); b < commitCnt.Uint64(); b++ { 502 | contract.Backend.Commit() //make block 503 | } 504 | } 505 | key, _ := crypto.GenerateKey() 506 | r, err := contract.Execute(key, "mint") 507 | assert.NoError(t, err) 508 | assert.True(t, r.Status == 1) 509 | countExpectedBalance() 510 | } 511 | endBlock := (*big.Int)(nil) 512 | assert.NoError(t, contract.Call(&endBlock, "blockToMint")) 513 | 514 | isMintable := bool(false) 515 | assert.NoError(t, contract.Call(&isMintable, "isMintable")) 516 | assert.True(t, isMintable == false) 517 | 518 | checkBalance := func(tag string, addr common.Address, expected *big.Int) { 519 | got := (*big.Int)(nil) 520 | assert.NoError(t, contract.Call(&got, "balanceOf", addr)) 521 | assert.True(t, expected.Cmp(got) == 0) 522 | t.Logf("ok > %s(%s) balance expected:%v, got:%v", tag, addr.Hex(), expected, got) 523 | } 524 | 525 | for a, expected := range balancePartners { 526 | checkBalance("partner", a, expected) 527 | } 528 | checkBalance("wemix", wemix, balanceWemix) 529 | checkBalance("ecoFund", ecoFund, balanceEcoFund) 530 | 531 | totalSupply := (*big.Int)(nil) 532 | assert.NoError(t, contract.Call(&totalSupply, "totalSupply")) 533 | expected := new(big.Int).Add(initialTotalSupply, totalMinted) 534 | assert.True(t, totalSupply.Cmp(expected) == 0) 535 | t.Logf("ok > match totalSupply and expected totalSupply after mint, got :%d, expectd: %d", totalSupply, expected) 536 | } 537 | 538 | //After registering block partners, do minting test and check the amount of minting. 539 | func TestWemixMint(t *testing.T) { 540 | contract := depolyWemix(t) 541 | testStake(t, contract, true) 542 | 543 | testMint(t, contract) 544 | } 545 | 546 | //Test minting without block partner and check minting amount. 547 | func TestWemixMintWithoutPartner(t *testing.T) { 548 | contract := depolyWemix(t) 549 | testMint(t, contract) 550 | } 551 | -------------------------------------------------------------------------------- /test/helper.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "bytes" 5 | "crypto/ecdsa" 6 | "encoding/gob" 7 | "math/big" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | 12 | "github.com/ethereum/go-ethereum/common" 13 | "github.com/wemade-tree/wemix-token/backend" 14 | ) 15 | 16 | type typeKeyMap map[common.Address]*ecdsa.PrivateKey 17 | 18 | //Converts the given data into a byte slice and returns it. 19 | func toBytes(t *testing.T, data interface{}) []byte { 20 | var buf bytes.Buffer 21 | assert.NoError(t, gob.NewEncoder(&buf).Encode(data)) 22 | return buf.Bytes() 23 | } 24 | 25 | //Converts the given number string based decimal number into big.Int type and returns it. 26 | func toBig(t *testing.T, value10 string) *big.Int { 27 | ret, b := new(big.Int).SetString(value10, 10) 28 | assert.True(t, b) 29 | return ret 30 | } 31 | 32 | //checkVariable compares value stored in the blockchain with a given expected value 33 | func checkVariable(t *testing.T, contract *backend.Contract, method string, expected interface{}) { 34 | ret, err := contract.LowCall(method) 35 | assert.NoError(t, err) 36 | assert.Equal(t, toBytes(t, ret[0]), toBytes(t, expected)) 37 | 38 | switch expected.(type) { 39 | case common.Address: 40 | t.Log(method, ret[0].(common.Address).Hex()) 41 | default: 42 | t.Log(method, ret[0]) 43 | } 44 | 45 | } 46 | 47 | //executeChangeMethod executes the method with the "change_" prefix in the contract, 48 | //and then compares whether the given arg argument is applied well. 49 | //The argument of "change_" prefixed method is assumed to be one. 50 | func executeChangeMethod(t *testing.T, contract *backend.Contract, methodExceptCall string, arg interface{}) { 51 | changeMethod := "change_" + methodExceptCall 52 | 53 | r, err := contract.Execute(nil, changeMethod, arg) 54 | assert.NoError(t, err) 55 | assert.True(t, r.Status == 1) 56 | 57 | changed, err := contract.LowCall(methodExceptCall) 58 | assert.NoError(t, err) 59 | assert.Equal(t, toBytes(t, changed[0]), toBytes(t, arg)) 60 | } 61 | 62 | //causes contract execution to fail. 63 | func expectedFail(t *testing.T, contract *backend.Contract, key *ecdsa.PrivateKey, method string, arg ...interface{}) { 64 | r, err := contract.Execute(key, method, arg...) 65 | assert.NoError(t, err) 66 | assert.True(t, r.Status == 0) 67 | } 68 | 69 | //checks if the contract execution is successful.. 70 | func expectedSuccess(t *testing.T, contract *backend.Contract, key *ecdsa.PrivateKey, method string, arg ...interface{}) { 71 | r, err := contract.Execute(key, method, arg...) 72 | assert.NoError(t, err) 73 | assert.True(t, r.Status == 1) 74 | } 75 | -------------------------------------------------------------------------------- /wemix_token_audit_report_20200624.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wemade-tree/wemix-token/fd15bb8818ca03b94ccd9a274a8d40d24d69c403/wemix_token_audit_report_20200624.pdf --------------------------------------------------------------------------------