Transaction Hash:
Block:
20246947 at Jul-06-2024 10:43:59 AM +UTC
Transaction Fee:
0.0000932591859264 ETH
$0.24
Gas Used:
29,952 Gas / 3.113621325 Gwei
Emitted Events:
16 |
BAToken.Transfer( _from=[Sender] 0x12ff8d6b7c90208b141e5aad4210da00b6fd061d, _to=GnosisSafeProxy, _value=2980007083530000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x0D8775F6...50d2887EF | |||||
0x12ff8D6b...0b6FD061d |
0.00072 Eth
Nonce: 0
|
0.0006267408140736 Eth
Nonce: 1
| 0.0000932591859264 | ||
0xf758C301...2d8bD2203
Miner
| (Fee Recipient: 0xf758...203) | 168.107582570303490144 Eth | 168.107612522303490144 Eth | 0.000029952 |
Execution Trace
BAToken.transfer( _to=0x27fD43BABfbe83a81d14665b1a6fB8030A60C9b4, _value=2980007083530000000000 ) => ( success=True )
transfer[Token (ln:35)]
File 1 of 2: BAToken
File 2 of 2: GnosisSafeProxy
pragma solidity ^0.4.10; /* taking ideas from FirstBlood token */ contract SafeMath { /* function assert(bool assertion) internal { */ /* if (!assertion) { */ /* throw; */ /* } */ /* } // assert no longer needed once solidity is on 0.4.10 */ function safeAdd(uint256 x, uint256 y) internal returns(uint256) { uint256 z = x + y; assert((z >= x) && (z >= y)); return z; } function safeSubtract(uint256 x, uint256 y) internal returns(uint256) { assert(x >= y); uint256 z = x - y; return z; } function safeMult(uint256 x, uint256 y) internal returns(uint256) { uint256 z = x * y; assert((x == 0)||(z/x == y)); return z; } } contract Token { uint256 public totalSupply; 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); } /* ERC 20 token */ contract StandardToken is Token { function transfer(address _to, uint256 _value) returns (bool success) { if (balances[msg.sender] >= _value && _value > 0) { balances[msg.sender] -= _value; balances[_to] += _value; Transfer(msg.sender, _to, _value); return true; } else { return false; } } function transferFrom(address _from, address _to, uint256 _value) returns (bool success) { if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) { balances[_to] += _value; balances[_from] -= _value; allowed[_from][msg.sender] -= _value; Transfer(_from, _to, _value); return true; } else { return false; } } function balanceOf(address _owner) constant returns (uint256 balance) { return balances[_owner]; } function approve(address _spender, uint256 _value) returns (bool success) { allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); 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 BAToken is StandardToken, SafeMath { // metadata string public constant name = "Basic Attention Token"; string public constant symbol = "BAT"; uint256 public constant decimals = 18; string public version = "1.0"; // contracts address public ethFundDeposit; // deposit address for ETH for Brave International address public batFundDeposit; // deposit address for Brave International use and BAT User Fund // crowdsale parameters bool public isFinalized; // switched to true in operational state uint256 public fundingStartBlock; uint256 public fundingEndBlock; uint256 public constant batFund = 500 * (10**6) * 10**decimals; // 500m BAT reserved for Brave Intl use uint256 public constant tokenExchangeRate = 6400; // 6400 BAT tokens per 1 ETH uint256 public constant tokenCreationCap = 1500 * (10**6) * 10**decimals; uint256 public constant tokenCreationMin = 675 * (10**6) * 10**decimals; // events event LogRefund(address indexed _to, uint256 _value); event CreateBAT(address indexed _to, uint256 _value); // constructor function BAToken( address _ethFundDeposit, address _batFundDeposit, uint256 _fundingStartBlock, uint256 _fundingEndBlock) { isFinalized = false; //controls pre through crowdsale state ethFundDeposit = _ethFundDeposit; batFundDeposit = _batFundDeposit; fundingStartBlock = _fundingStartBlock; fundingEndBlock = _fundingEndBlock; totalSupply = batFund; balances[batFundDeposit] = batFund; // Deposit Brave Intl share CreateBAT(batFundDeposit, batFund); // logs Brave Intl fund } /// @dev Accepts ether and creates new BAT tokens. function createTokens() payable external { if (isFinalized) throw; if (block.number < fundingStartBlock) throw; if (block.number > fundingEndBlock) throw; if (msg.value == 0) throw; uint256 tokens = safeMult(msg.value, tokenExchangeRate); // check that we're not over totals uint256 checkedSupply = safeAdd(totalSupply, tokens); // return money if something goes wrong if (tokenCreationCap < checkedSupply) throw; // odd fractions won't be found totalSupply = checkedSupply; balances[msg.sender] += tokens; // safeAdd not needed; bad semantics to use here CreateBAT(msg.sender, tokens); // logs token creation } /// @dev Ends the funding period and sends the ETH home function finalize() external { if (isFinalized) throw; if (msg.sender != ethFundDeposit) throw; // locks finalize to the ultimate ETH owner if(totalSupply < tokenCreationMin) throw; // have to sell minimum to move to operational if(block.number <= fundingEndBlock && totalSupply != tokenCreationCap) throw; // move to operational isFinalized = true; if(!ethFundDeposit.send(this.balance)) throw; // send the eth to Brave International } /// @dev Allows contributors to recover their ether in the case of a failed funding campaign. function refund() external { if(isFinalized) throw; // prevents refund if operational if (block.number <= fundingEndBlock) throw; // prevents refund until sale period is over if(totalSupply >= tokenCreationMin) throw; // no refunds if we sold enough if(msg.sender == batFundDeposit) throw; // Brave Intl not entitled to a refund uint256 batVal = balances[msg.sender]; if (batVal == 0) throw; balances[msg.sender] = 0; totalSupply = safeSubtract(totalSupply, batVal); // extra safe uint256 ethVal = batVal / tokenExchangeRate; // should be safe; previous throws covers edges LogRefund(msg.sender, ethVal); // log it if (!msg.sender.send(ethVal)) throw; // if you're using a contract; make sure it works with .send gas limits } }
File 2 of 2: GnosisSafeProxy
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title IProxy - Helper interface to access masterCopy of the Proxy on-chain /// @author Richard Meissner - <[email protected]> interface IProxy { function masterCopy() external view returns (address); } /// @title GnosisSafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract. /// @author Stefan George - <[email protected]> /// @author Richard Meissner - <[email protected]> contract GnosisSafeProxy { // singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated. // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt` address internal singleton; /// @dev Constructor function sets address of singleton contract. /// @param _singleton Singleton address. constructor(address _singleton) { require(_singleton != address(0), "Invalid singleton address provided"); singleton = _singleton; } /// @dev Fallback function forwards all transactions and returns all received return data. fallback() external payable { // solhint-disable-next-line no-inline-assembly assembly { let _singleton := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff) // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) { mstore(0, _singleton) return(0, 0x20) } calldatacopy(0, 0, calldatasize()) let success := delegatecall(gas(), _singleton, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) if eq(success, 0) { revert(0, returndatasize()) } return(0, returndatasize()) } } } /// @title Proxy Factory - Allows to create new proxy contact and execute a message call to the new proxy within one transaction. /// @author Stefan George - <[email protected]> contract GnosisSafeProxyFactory { event ProxyCreation(GnosisSafeProxy proxy, address singleton); /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction. /// @param singleton Address of singleton contract. /// @param data Payload for message call sent to new proxy contract. function createProxy(address singleton, bytes memory data) public returns (GnosisSafeProxy proxy) { proxy = new GnosisSafeProxy(singleton); if (data.length > 0) // solhint-disable-next-line no-inline-assembly assembly { if eq(call(gas(), proxy, 0, add(data, 0x20), mload(data), 0, 0), 0) { revert(0, 0) } } emit ProxyCreation(proxy, singleton); } /// @dev Allows to retrieve the runtime code of a deployed Proxy. This can be used to check that the expected Proxy was deployed. function proxyRuntimeCode() public pure returns (bytes memory) { return type(GnosisSafeProxy).runtimeCode; } /// @dev Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address. function proxyCreationCode() public pure returns (bytes memory) { return type(GnosisSafeProxy).creationCode; } /// @dev Allows to create new proxy contact using CREATE2 but it doesn't run the initializer. /// This method is only meant as an utility to be called from other methods /// @param _singleton Address of singleton contract. /// @param initializer Payload for message call sent to new proxy contract. /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. function deployProxyWithNonce( address _singleton, bytes memory initializer, uint256 saltNonce ) internal returns (GnosisSafeProxy proxy) { // If the initializer changes the proxy address should change too. Hashing the initializer data is cheaper than just concatinating it bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce)); bytes memory deploymentData = abi.encodePacked(type(GnosisSafeProxy).creationCode, uint256(uint160(_singleton))); // solhint-disable-next-line no-inline-assembly assembly { proxy := create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt) } require(address(proxy) != address(0), "Create2 call failed"); } /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction. /// @param _singleton Address of singleton contract. /// @param initializer Payload for message call sent to new proxy contract. /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. function createProxyWithNonce( address _singleton, bytes memory initializer, uint256 saltNonce ) public returns (GnosisSafeProxy proxy) { proxy = deployProxyWithNonce(_singleton, initializer, saltNonce); if (initializer.length > 0) // solhint-disable-next-line no-inline-assembly assembly { if eq(call(gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0), 0) { revert(0, 0) } } emit ProxyCreation(proxy, _singleton); } /// @dev Allows to create new proxy contact, execute a message call to the new proxy and call a specified callback within one transaction /// @param _singleton Address of singleton contract. /// @param initializer Payload for message call sent to new proxy contract. /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. /// @param callback Callback that will be invoced after the new proxy contract has been successfully deployed and initialized. function createProxyWithCallback( address _singleton, bytes memory initializer, uint256 saltNonce, IProxyCreationCallback callback ) public returns (GnosisSafeProxy proxy) { uint256 saltNonceWithCallback = uint256(keccak256(abi.encodePacked(saltNonce, callback))); proxy = createProxyWithNonce(_singleton, initializer, saltNonceWithCallback); if (address(callback) != address(0)) callback.proxyCreated(proxy, _singleton, initializer, saltNonce); } /// @dev Allows to get the address for a new proxy contact created via `createProxyWithNonce` /// This method is only meant for address calculation purpose when you use an initializer that would revert, /// therefore the response is returned with a revert. When calling this method set `from` to the address of the proxy factory. /// @param _singleton Address of singleton contract. /// @param initializer Payload for message call sent to new proxy contract. /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. function calculateCreateProxyWithNonceAddress( address _singleton, bytes calldata initializer, uint256 saltNonce ) external returns (GnosisSafeProxy proxy) { proxy = deployProxyWithNonce(_singleton, initializer, saltNonce); revert(string(abi.encodePacked(proxy))); } } interface IProxyCreationCallback { function proxyCreated( GnosisSafeProxy proxy, address _singleton, bytes calldata initializer, uint256 saltNonce ) external; }