ETH Price: $2,123.65 (-3.06%)

Transaction Decoder

Block:
13498943 at Oct-27-2021 10:45:24 AM +UTC
Transaction Fee:
0.005167548682015935 ETH $10.97
Gas Used:
45,231 Gas / 114.247942385 Gwei

Emitted Events:

554 C20.Withdraw( participant=[Sender] 0xae83c2fc7260a4fd1df0eea3167eb7eb974391c9, amountTokens=487308039450000000000, etherAmount=643141425522086152 )

Account State Difference:

  Address   Before After State Difference Code
0x26E75307...1F112f317 275.72254031081368397 Eth275.079398885291597818 Eth0.643141425522086152
0xAE83C2FC...b974391c9
0.487540304214927023 Eth
Nonce: 3
1.12551418105499724 Eth
Nonce: 4
0.637973876840070217
(KuCoin Pool)
2,650.315556130022620235 Eth2,650.315607331620551237 Eth0.000051201597931002

Execution Trace

C20.CALL( )
  • ETH 0.643141425522086152 0xae83c2fc7260a4fd1df0eea3167eb7eb974391c9.CALL( )
    pragma solidity 0.4.11;
    
    contract SafeMath {
    
      function safeMul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
      function safeSub(uint a, uint b) internal returns (uint) {
        assert(b <= a);
        return a - b;
      }
      function safeAdd(uint a, uint b) internal returns (uint) {
        uint c = a + b;
        assert(c>=a && c>=b);
        return c;
      }
    
      // mitigate short address attack
      // thanks to https://github.com/numerai/contract/blob/c182465f82e50ced8dacb3977ec374a892f5fa8c/contracts/Safe.sol#L30-L34.
      // TODO: doublecheck implication of >= compared to ==
      modifier onlyPayloadSize(uint numWords) {
         assert(msg.data.length >= numWords * 32 + 4);
         _;
      }
    
    }
    
    
    contract Token { // ERC20 standard
    
        function balanceOf(address _owner) constant returns (uint256 balance);
        function transfer(address _to, uint256 _value) returns (bool success);
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
        function approve(address _spender, uint256 _value) returns (bool success);
        function allowance(address _owner, address _spender) constant returns (uint256 remaining);
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    }
    
    
    contract StandardToken is Token, SafeMath {
    
        uint256 public totalSupply;
    
        // TODO: update tests to expect throw
        function transfer(address _to, uint256 _value) onlyPayloadSize(2) returns (bool success) {
            require(_to != address(0));
            require(balances[msg.sender] >= _value && _value > 0);
            balances[msg.sender] = safeSub(balances[msg.sender], _value);
            balances[_to] = safeAdd(balances[_to], _value);
            Transfer(msg.sender, _to, _value);
    
            return true;
        }
    
        // TODO: update tests to expect throw
        function transferFrom(address _from, address _to, uint256 _value) onlyPayloadSize(3) returns (bool success) {
            require(_to != address(0));
            require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0);
            balances[_from] = safeSub(balances[_from], _value);
            balances[_to] = safeAdd(balances[_to], _value);
            allowed[_from][msg.sender] = safeSub(allowed[_from][msg.sender], _value);
            Transfer(_from, _to, _value);
    
            return true;
        }
    
        function balanceOf(address _owner) constant returns (uint256 balance) {
            return balances[_owner];
        }
    
        // To change the approve amount you first have to reduce the addresses'
        //  allowance to zero by calling 'approve(_spender, 0)' if it is not
        //  already 0 to mitigate the race condition described here:
        //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        function approve(address _spender, uint256 _value) onlyPayloadSize(2) returns (bool success) {
            require((_value == 0) || (allowed[msg.sender][_spender] == 0));
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
    
            return true;
        }
    
        function changeApproval(address _spender, uint256 _oldValue, uint256 _newValue) onlyPayloadSize(3) returns (bool success) {
            require(allowed[msg.sender][_spender] == _oldValue);
            allowed[msg.sender][_spender] = _newValue;
            Approval(msg.sender, _spender, _newValue);
    
            return true;
        }
    
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
          return allowed[_owner][_spender];
        }
    
        mapping (address => uint256) balances;
        mapping (address => mapping (address => uint256)) allowed;
    
    }
    
    
    contract C20 is StandardToken {
    
        // FIELDS
    
        string public name = "Crypto20";
        string public symbol = "C20";
        uint256 public decimals = 18;
        string public version = "9.0";
    
        uint256 public tokenCap = 86206896 * 10**18;
    
        // crowdsale parameters
        uint256 public fundingStartBlock;
        uint256 public fundingEndBlock;
    
        // vesting fields
        address public vestingContract;
        bool private vestingSet = false;
    
        // root control
        address public fundWallet;
        // control of liquidity and limited control of updatePrice
        address public controlWallet;
        // time to wait between controlWallet price updates
        uint256 public waitTime = 5 hours;
    
        // fundWallet controlled state variables
        // halted: halt buying due to emergency, tradeable: signal that assets have been acquired
        bool public halted = false;
        bool public tradeable = false;
    
        // -- totalSupply defined in StandardToken
        // -- mapping to token balances done in StandardToken
    
        uint256 public previousUpdateTime = 0;
        Price public currentPrice;
        uint256 public minAmount = 0.04 ether;
    
        // map participant address to a withdrawal request
        mapping (address => Withdrawal) public withdrawals;
        // maps previousUpdateTime to the next price
        mapping (uint256 => Price) public prices;
        // maps addresses
        mapping (address => bool) public whitelist;
    
        // TYPES
    
        struct Price { // tokensPerEth
            uint256 numerator;
            uint256 denominator;
        }
    
        struct Withdrawal {
            uint256 tokens;
            uint256 time; // time for each withdrawal is set to the previousUpdateTime
        }
    
        // EVENTS
    
        event Buy(address indexed participant, address indexed beneficiary, uint256 ethValue, uint256 amountTokens);
        event AllocatePresale(address indexed participant, uint256 amountTokens);
        event Whitelist(address indexed participant);
        event PriceUpdate(uint256 numerator, uint256 denominator);
        event AddLiquidity(uint256 ethAmount);
        event RemoveLiquidity(uint256 ethAmount);
        event WithdrawRequest(address indexed participant, uint256 amountTokens);
        event Withdraw(address indexed participant, uint256 amountTokens, uint256 etherAmount);
    
        // MODIFIERS
    
        modifier isTradeable { // exempt vestingContract and fundWallet to allow dev allocations
            require(tradeable || msg.sender == fundWallet || msg.sender == vestingContract);
            _;
        }
    
        modifier onlyWhitelist {
            require(whitelist[msg.sender]);
            _;
        }
    
        modifier onlyFundWallet {
            require(msg.sender == fundWallet);
            _;
        }
    
        modifier onlyManagingWallets {
            require(msg.sender == controlWallet || msg.sender == fundWallet);
            _;
        }
    
        modifier only_if_controlWallet {
            if (msg.sender == controlWallet) _;
        }
        modifier require_waited {
            require(safeSub(now, waitTime) >= previousUpdateTime);
            _;
        }
        modifier only_if_increase (uint256 newNumerator) {
            if (newNumerator > currentPrice.numerator) _;
        }
    
        // CONSTRUCTOR
    
        function C20(address controlWalletInput, uint256 priceNumeratorInput, uint256 startBlockInput, uint256 endBlockInput) {
            require(controlWalletInput != address(0));
            require(priceNumeratorInput > 0);
            require(endBlockInput > startBlockInput);
            fundWallet = msg.sender;
            controlWallet = controlWalletInput;
            whitelist[fundWallet] = true;
            whitelist[controlWallet] = true;
            currentPrice = Price(priceNumeratorInput, 1000); // 1 token = 1 usd at ICO start
            fundingStartBlock = startBlockInput;
            fundingEndBlock = endBlockInput;
            previousUpdateTime = now;
        }
    
        // METHODS
    
        function setVestingContract(address vestingContractInput) external onlyFundWallet {
            require(vestingContractInput != address(0));
            vestingContract = vestingContractInput;
            whitelist[vestingContract] = true;
            vestingSet = true;
        }
    
        // allows controlWallet to update the price within a time contstraint, allows fundWallet complete control
        function updatePrice(uint256 newNumerator) external onlyManagingWallets {
            require(newNumerator > 0);
            require_limited_change(newNumerator);
            // either controlWallet command is compliant or transaction came from fundWallet
            currentPrice.numerator = newNumerator;
            // maps time to new Price (if not during ICO)
            prices[previousUpdateTime] = currentPrice;
            previousUpdateTime = now;
            PriceUpdate(newNumerator, currentPrice.denominator);
        }
    
        function require_limited_change (uint256 newNumerator)
            private
            only_if_controlWallet
            require_waited
            only_if_increase(newNumerator)
        {
            uint256 percentage_diff = 0;
            percentage_diff = safeMul(newNumerator, 100) / currentPrice.numerator;
            percentage_diff = safeSub(percentage_diff, 100);
            // controlWallet can only increase price by max 20% and only every waitTime
            require(percentage_diff <= 20);
        }
    
        function updatePriceDenominator(uint256 newDenominator) external onlyFundWallet {
            require(block.number > fundingEndBlock);
            require(newDenominator > 0);
            currentPrice.denominator = newDenominator;
            // maps time to new Price
            prices[previousUpdateTime] = currentPrice;
            previousUpdateTime = now;
            PriceUpdate(currentPrice.numerator, newDenominator);
        }
    
        function allocateTokens(address participant, uint256 amountTokens) private {
            require(vestingSet);
            // 13% of total allocated for PR, Marketing, Team, Advisors
            uint256 developmentAllocation = safeMul(amountTokens, 14942528735632185) / 100000000000000000;
            // check that token cap is not exceeded
            uint256 newTokens = safeAdd(amountTokens, developmentAllocation);
            require(safeAdd(totalSupply, newTokens) <= tokenCap);
            // increase token supply, assign tokens to participant
            totalSupply = safeAdd(totalSupply, newTokens);
            balances[participant] = safeAdd(balances[participant], amountTokens);
            balances[vestingContract] = safeAdd(balances[vestingContract], developmentAllocation);
        }
    
        function allocatePresaleTokens(address participant, uint amountTokens) external onlyFundWallet {
            require(block.number < fundingEndBlock);
            require(participant != address(0));
            whitelist[participant] = true; // automatically whitelist accepted presale
            allocateTokens(participant, amountTokens);
            Whitelist(participant);
            AllocatePresale(participant, amountTokens);
        }
    
        function verifyParticipant(address participant) external onlyManagingWallets {
            whitelist[participant] = true;
            Whitelist(participant);
        }
    
        function buy() external payable {
            buyTo(msg.sender);
        }
    
        function buyTo(address participant) public payable onlyWhitelist {
            require(!halted);
            require(participant != address(0));
            require(msg.value >= minAmount);
            require(block.number >= fundingStartBlock && block.number < fundingEndBlock);
            uint256 icoDenominator = icoDenominatorPrice();
            uint256 tokensToBuy = safeMul(msg.value, currentPrice.numerator) / icoDenominator;
            allocateTokens(participant, tokensToBuy);
            // send ether to fundWallet
            fundWallet.transfer(msg.value);
            Buy(msg.sender, participant, msg.value, tokensToBuy);
        }
    
        // time based on blocknumbers, assuming a blocktime of 30s
        function icoDenominatorPrice() public constant returns (uint256) {
            uint256 icoDuration = safeSub(block.number, fundingStartBlock);
            uint256 denominator;
            if (icoDuration < 2880) { // #blocks = 24*60*60/30 = 2880
                return currentPrice.denominator;
            } else if (icoDuration < 80640 ) { // #blocks = 4*7*24*60*60/30 = 80640
                denominator = safeMul(currentPrice.denominator, 105) / 100;
                return denominator;
            } else {
                denominator = safeMul(currentPrice.denominator, 110) / 100;
                return denominator;
            }
        }
    
        function requestWithdrawal(uint256 amountTokensToWithdraw) external isTradeable onlyWhitelist {
            require(block.number > fundingEndBlock);
            require(amountTokensToWithdraw > 0);
            address participant = msg.sender;
            require(balanceOf(participant) >= amountTokensToWithdraw);
            require(withdrawals[participant].tokens == 0); // participant cannot have outstanding withdrawals
            balances[participant] = safeSub(balances[participant], amountTokensToWithdraw);
            withdrawals[participant] = Withdrawal({tokens: amountTokensToWithdraw, time: previousUpdateTime});
            WithdrawRequest(participant, amountTokensToWithdraw);
        }
    
        function withdraw() external {
            address participant = msg.sender;
            uint256 tokens = withdrawals[participant].tokens;
            require(tokens > 0); // participant must have requested a withdrawal
            uint256 requestTime = withdrawals[participant].time;
            // obtain the next price that was set after the request
            Price price = prices[requestTime];
            require(price.numerator > 0); // price must have been set
            uint256 withdrawValue = safeMul(tokens, price.denominator) / price.numerator;
            // if contract ethbal > then send + transfer tokens to fundWallet, otherwise give tokens back
            withdrawals[participant].tokens = 0;
            if (this.balance >= withdrawValue)
                enact_withdrawal_greater_equal(participant, withdrawValue, tokens);
            else
                enact_withdrawal_less(participant, withdrawValue, tokens);
        }
    
        function enact_withdrawal_greater_equal(address participant, uint256 withdrawValue, uint256 tokens)
            private
        {
            assert(this.balance >= withdrawValue);
            balances[fundWallet] = safeAdd(balances[fundWallet], tokens);
            participant.transfer(withdrawValue);
            Withdraw(participant, tokens, withdrawValue);
        }
        function enact_withdrawal_less(address participant, uint256 withdrawValue, uint256 tokens)
            private
        {
            assert(this.balance < withdrawValue);
            balances[participant] = safeAdd(balances[participant], tokens);
            Withdraw(participant, tokens, 0); // indicate a failed withdrawal
        }
    
    
        function checkWithdrawValue(uint256 amountTokensToWithdraw) constant returns (uint256 etherValue) {
            require(amountTokensToWithdraw > 0);
            require(balanceOf(msg.sender) >= amountTokensToWithdraw);
            uint256 withdrawValue = safeMul(amountTokensToWithdraw, currentPrice.denominator) / currentPrice.numerator;
            require(this.balance >= withdrawValue);
            return withdrawValue;
        }
    
        // allow fundWallet or controlWallet to add ether to contract
        function addLiquidity() external onlyManagingWallets payable {
            require(msg.value > 0);
            AddLiquidity(msg.value);
        }
    
        // allow fundWallet to remove ether from contract
        function removeLiquidity(uint256 amount) external onlyManagingWallets {
            require(amount <= this.balance);
            fundWallet.transfer(amount);
            RemoveLiquidity(amount);
        }
    
        function changeFundWallet(address newFundWallet) external onlyFundWallet {
            require(newFundWallet != address(0));
            fundWallet = newFundWallet;
        }
    
        function changeControlWallet(address newControlWallet) external onlyFundWallet {
            require(newControlWallet != address(0));
            controlWallet = newControlWallet;
        }
    
        function changeWaitTime(uint256 newWaitTime) external onlyFundWallet {
            waitTime = newWaitTime;
        }
    
        function updateFundingStartBlock(uint256 newFundingStartBlock) external onlyFundWallet {
            require(block.number < fundingStartBlock);
            require(block.number < newFundingStartBlock);
            fundingStartBlock = newFundingStartBlock;
        }
    
        function updateFundingEndBlock(uint256 newFundingEndBlock) external onlyFundWallet {
            require(block.number < fundingEndBlock);
            require(block.number < newFundingEndBlock);
            fundingEndBlock = newFundingEndBlock;
        }
    
        function halt() external onlyFundWallet {
            halted = true;
        }
        function unhalt() external onlyFundWallet {
            halted = false;
        }
    
        function enableTrading() external onlyFundWallet {
            require(block.number > fundingEndBlock);
            tradeable = true;
        }
    
        // fallback function
        function() payable {
            require(tx.origin == msg.sender);
            buyTo(msg.sender);
        }
    
        function claimTokens(address _token) external onlyFundWallet {
            require(_token != address(0));
            Token token = Token(_token);
            uint256 balance = token.balanceOf(this);
            token.transfer(fundWallet, balance);
         }
    
        // prevent transfers until trading allowed
        function transfer(address _to, uint256 _value) isTradeable returns (bool success) {
            return super.transfer(_to, _value);
        }
        function transferFrom(address _from, address _to, uint256 _value) isTradeable returns (bool success) {
            return super.transferFrom(_from, _to, _value);
        }
    
    }