Transaction Hash:
Block:
11235427 at Nov-11-2020 09:12:23 AM +UTC
Transaction Fee:
0.001431 ETH
$3.67
Gas Used:
23,850 Gas / 60 Gwei
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x5491FbcD...b4e534367 |
0.005972293 Eth
Nonce: 7
|
0.004541293 Eth
Nonce: 8
| 0.001431 | ||
0x829BD824...93333A830
Miner
| (F2Pool Old) | 5,038.346549854613517868 Eth | 5,038.347980854613517868 Eth | 0.001431 |
Execution Trace
NativeSwap.withdraw( _amount=124314658480083651439764 )
withdraw[NativeSwap (ln:329)]
sub[NativeSwap (ln:331)]
transfer[NativeSwap (ln:334)]
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: contracts/interfaces/IToken.sol pragma solidity ^0.6.0; interface IToken { function mint(address to, uint256 amount) external; function burn(address from, uint256 amount) external; } // File: contracts/interfaces/IAuction.sol pragma solidity ^0.6.0; interface IAuction { function callIncomeDailyTokensTrigger(uint256 amount) external; function callIncomeWeeklyTokensTrigger(uint256 amount) external; } // File: contracts/NativeSwap.sol pragma solidity >=0.4.25 <0.7.0; contract NativeSwap { using SafeMath for uint256; event TokensSwapped( address indexed account, uint256 indexed stepsFromStart, uint256 userAmount, uint256 penaltyAmount ); uint256 public start; uint256 public period; uint256 public stepTimestamp; IERC20 public swapToken; IToken public mainToken; IAuction public auction; bool public init_; mapping(address => uint256) public swapTokenBalanceOf; constructor() public { init_ = false; } function init( uint256 _period, uint256 _stepTimestamp, address _swapToken, address _mainToken, address _auction ) external { require(!init_, "init is active"); period = _period; stepTimestamp = _stepTimestamp; swapToken = IERC20(_swapToken); mainToken = IToken(_mainToken); auction = IAuction(_auction); start = now; init_ = true; } function deposit(uint256 _amount) external { require( swapToken.transferFrom(msg.sender, address(this), _amount), "NativeSwap: transferFrom error" ); swapTokenBalanceOf[msg.sender] = swapTokenBalanceOf[msg.sender].add( _amount ); } function withdraw(uint256 _amount) external { require(_amount >= swapTokenBalanceOf[msg.sender], "balance < amount"); swapTokenBalanceOf[msg.sender] = swapTokenBalanceOf[msg.sender].sub( _amount ); swapToken.transfer(msg.sender, _amount); } function swapNativeToken() external { uint256 stepsFromStart = calculateStepsFromStart(); require(stepsFromStart <= period, "swapNativeToken: swap is over"); uint256 amount = swapTokenBalanceOf[msg.sender]; uint256 deltaPenalty = calculateDeltaPenalty(amount); uint256 amountOut = amount.sub(deltaPenalty); require(amount > 0, "swapNativeToken: amount == 0"); swapTokenBalanceOf[msg.sender] = 0; mainToken.mint(address(auction), deltaPenalty); auction.callIncomeDailyTokensTrigger(deltaPenalty); mainToken.mint(msg.sender, amountOut); emit TokensSwapped(msg.sender, stepsFromStart, amount, deltaPenalty); } function calculateDeltaPenalty(uint256 amount) public view returns (uint256) { uint256 stepsFromStart = calculateStepsFromStart(); if (stepsFromStart > period) return amount; return amount.mul(stepsFromStart).div(period); } function calculateStepsFromStart() public view returns (uint256) { return now.sub(start).div(stepTimestamp); } }