Transaction Hash:
Block:
14266780 at Feb-24-2022 05:02:25 AM +UTC
Transaction Fee:
0.005040110672077626 ETH
$12.34
Gas Used:
37,286 Gas / 135.174346191 Gwei
Emitted Events:
69 |
DharmaGasReserve.Call( target=0x67e1b186e6da49917922c040fd07be1827978ce7, amount=10343297491553321561, data=0x, ok=True, returnData=0x )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x55F20393...Fed386dBf | 10.343297491553321561 Eth | 0 Eth | 10.343297491553321561 | ||
0x67e1b186...827978CE7 | 26.741831454404852682 Eth | 37.085128945958174243 Eth | 10.343297491553321561 | ||
0x7e4A8391...6628B19Fa | (Dharma: Deployer) |
0.651443771156257049 Eth
Nonce: 1464
|
0.646403660484179423 Eth
Nonce: 1465
| 0.005040110672077626 | |
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 1,948.875499954828416175 Eth | 1,948.875581984028416175 Eth | 0.0000820292 |
Execution Trace
DharmaGasReserve.callAny( target=0x67e1b186e6dA49917922C040FD07bE1827978CE7, amount=10343297491553321561, data=0x ) => ( ok=True, returnData=0x )
- ETH 10.343297491553321561
0x67e1b186e6da49917922c040fd07be1827978ce7.CALL( )
pragma solidity 0.5.17; interface DharmaGasReserveInterface { // events event EtherReceived(address sender, uint256 amount); event Pulled(address indexed gasAccount, uint256 amount); event AddedGasAccount(address gasAccount); event RemovedGasAccount(address gasAccount); event NewPullAmount(uint256 pullAmount); event NewRateLimit(uint256 interval); event Call(address target, uint256 amount, bytes data, bool ok, bytes returnData); // only callable by designated "gas accounts" function pullGas() external; // only callable by owner function addGasAccount(address gasAccount) external; function removeGasAccount(address gasAccount) external; function setPullAmount(uint256 amount) external; function setRateLimit(uint256 interval) external; function callAny( address payable target, uint256 amount, bytes calldata data ) external returns (bool ok, bytes memory returnData); // view functions function getGasAccounts() external view returns (address[] memory); function getPullAmount() external view returns (uint256); function getRateLimit() external view returns (uint256); function getLastPullTime(address gasAccount) external view returns (uint256); } contract TwoStepOwnable { address private _owner; address private _newPotentialOwner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Initialize contract by setting transaction submitter as initial owner. */ constructor() internal { _owner = tx.origin; emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "TwoStepOwnable: caller is not the owner."); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows a new account (`newOwner`) to accept ownership. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { require( newOwner != address(0), "TwoStepOwnable: new potential owner is the zero address." ); _newPotentialOwner = newOwner; } /** * @dev Cancel a transfer of ownership to a new account. * Can only be called by the current owner. */ function cancelOwnershipTransfer() public onlyOwner { delete _newPotentialOwner; } /** * @dev Transfers ownership of the contract to the caller. * Can only be called by a new potential owner set by the current owner. */ function acceptOwnership() public { require( msg.sender == _newPotentialOwner, "TwoStepOwnable: current owner must set caller as new potential owner." ); delete _newPotentialOwner; emit OwnershipTransferred(_owner, msg.sender); _owner = msg.sender; } } contract DharmaGasReserve is DharmaGasReserveInterface, TwoStepOwnable { // Track all authorized gas accounts. address[] private _gasAccounts; // Indexes start at 1, as 0 signifies non-inclusion mapping (address => uint256) private _gasAccountIndexes; mapping (address => uint256) private _lastPullTime; uint256 private _pullAmount; uint256 private _rateLimit; constructor(address[] memory initialGasAccounts) public { _setPullAmount(3 ether); _setRateLimit(1 hours); for (uint256 i; i < initialGasAccounts.length; i++) { address gasAccount = initialGasAccounts[i]; _addGasAccount(gasAccount); } } function () external payable { if (msg.value > 0) { emit EtherReceived(msg.sender, msg.value); } } function pullGas() external { require( _gasAccountIndexes[msg.sender] != 0, "Only authorized gas accounts may pull from this contract." ); require( msg.sender.balance < _pullAmount, "Gas account balance is not yet below the pull amount." ); require( now > _lastPullTime[msg.sender] + _rateLimit, "Gas account is currently rate-limited." ); _lastPullTime[msg.sender] = now; uint256 pullAmount = _pullAmount; require( address(this).balance >= pullAmount, "Insufficient funds held by the reserve." ); (bool ok, ) = msg.sender.call.value(pullAmount)(""); if (!ok) { assembly { returndatacopy(0, 0, returndatasize) revert(0, returndatasize) } } emit Pulled(msg.sender, pullAmount); } function addGasAccount(address gasAccount) external onlyOwner { _addGasAccount(gasAccount); } function removeGasAccount(address gasAccount) external onlyOwner { _removeGasAccount(gasAccount); } function setPullAmount(uint256 amount) external onlyOwner { _setPullAmount(amount); } function setRateLimit(uint256 interval) external onlyOwner { _setRateLimit(interval); } function callAny( address payable target, uint256 amount, bytes calldata data ) external onlyOwner returns (bool ok, bytes memory returnData) { // Call the specified target and supply the specified data. (ok, returnData) = target.call.value(amount)(data); emit Call(target, amount, data, ok, returnData); } function getGasAccounts() external view returns (address[] memory) { return _gasAccounts; } function getPullAmount() external view returns (uint256) { return _pullAmount; } function getRateLimit() external view returns (uint256) { return _rateLimit; } function getLastPullTime(address gasAccount) external view returns (uint256) { return _lastPullTime[gasAccount]; } function _addGasAccount(address gasAccount) internal { require( _gasAccountIndexes[gasAccount] == 0, "Gas account matching the provided account already exists." ); _gasAccounts.push(gasAccount); _gasAccountIndexes[gasAccount] = _gasAccounts.length; emit AddedGasAccount(gasAccount); } function _removeGasAccount(address gasAccount) internal { uint256 removedGasAccountIndex = _gasAccountIndexes[gasAccount]; require( removedGasAccountIndex != 0, "No gas account found matching the provided account." ); // swap account to remove with the last one then pop from the array. address lastGasAccount = _gasAccounts[_gasAccounts.length - 1]; _gasAccounts[removedGasAccountIndex - 1] = lastGasAccount; _gasAccountIndexes[lastGasAccount] = removedGasAccountIndex; _gasAccounts.pop(); delete _gasAccountIndexes[gasAccount]; emit RemovedGasAccount(gasAccount); } function _setPullAmount(uint256 amount) internal { _pullAmount = amount; emit NewPullAmount(amount); } function _setRateLimit(uint256 interval) internal { _rateLimit = interval; emit NewRateLimit(interval); } }