Last active
January 21, 2021 14:17
-
-
Save RyanHendricks/2166313b6b2e01b513d93101577a4f15 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.0 <0.7.0; | |
library GetCode { | |
function at(address _addr) public view returns (bytes memory o_code) { | |
assembly { | |
// retrieve the size of the code, this needs assembly | |
let size := extcodesize(_addr) | |
// allocate output byte array - this could also be done without assembly | |
// by using o_code = new bytes(size) | |
o_code := mload(0x40) | |
// new "memory end" including padding | |
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) | |
// store length in memory | |
mstore(o_code, size) | |
// actually retrieve the code, this needs assembly | |
extcodecopy(_addr, add(o_code, 0x20), 0, size) | |
} | |
} | |
} | |
contract TestETL { | |
using GetCode for *; | |
address public creator; | |
address public creatorproxy; | |
/** | |
* @dev contructor function which sets creator and creator proxy | |
* @param _proxy address of proxy contract for proxied calls | |
*/ | |
constructor (address _proxy) public { | |
creator = msg.sender; | |
creatorproxy = _proxy; | |
} | |
/// Events to log information cheaply and repeatedly | |
/// msg.sender vs tx.origin log | |
event txSenderInfo(address sender, address origin); | |
/// gas metrics | |
event gasInfo(uint remainingGas, uint txGasPrice, uint blockGasLimit); | |
/// balance details | |
event balanceInfo(address balanceHolder, uint256 balance); | |
/// block details | |
event blockInfo(address coinbase, uint difficulty, uint blockNumber, uint timestamp); | |
/// call details | |
event callInfo(bytes4 msgsig, uint msgvalue); | |
// Fallback function to allow ETH into contract | |
function deposit() public payable { | |
logBlockInfo(); | |
logGasInfo(); | |
logCallInfo(msg.sig, msg.value); | |
logTxSenderInfo(); | |
} | |
modifier restricted() { | |
require(msg.sender == creator || msg.sender == creatorproxy, "unauthorized"); | |
_; | |
} | |
function getCode(address _contract) public view returns (bytes memory code) { | |
return GetCode.at(_contract); | |
} | |
/** | |
* Helper functions for event emissions | |
*/ | |
/// @dev logs details about the origin of a transaction | |
function logTxSenderInfo() public { | |
emit txSenderInfo(msg.sender, tx.origin); | |
} | |
/// @dev logs the gas, gasprice and block gaslimit | |
function logGasInfo() public { | |
emit gasInfo(gasleft(), tx.gasprice, block.gaslimit); | |
} | |
function logCallInfo(bytes4 sig, uint256 val) public { | |
emit callInfo(sig, val); | |
} | |
/// @dev logs the coinbase difficulty number and timestamp for the block | |
function logBlockInfo() public { | |
emit blockInfo( | |
block.coinbase, | |
block.difficulty, | |
block.number, | |
block.timestamp | |
); | |
} | |
/// @dev logs the balance for an address | |
function logBalanceInfo(address _balanceHolder, uint256 _balance) public { | |
emit balanceInfo(_balanceHolder, _balance); | |
} | |
function eventEncode(string memory _forEncoding) public restricted view returns (bytes4) { | |
return bytes4(keccak256(abi.encodePacked(_forEncoding))); | |
} | |
// deprecated in version 0.4.22 and replaced by blockhash(uint blockNumber). | |
function getBlockHash(uint _blockNumber) public payable returns (bytes32 _hash) { | |
// blockHash() for later versions | |
logBlockInfo(); | |
logGasInfo(); | |
logCallInfo(msg.sig, msg.value); | |
logTxSenderInfo(); | |
return blockhash(_blockNumber); | |
} | |
/// @dev Test function number 1 | |
function checkBalanceSendEth(address payable _recipient) public payable { | |
/// log balance at the start | |
checkBalance(_recipient); | |
/// transfer recipient smallest unit possible | |
_recipient.transfer(1); | |
/// log balance | |
checkBalance(_recipient); | |
/// send recipient smallest unit possible | |
_recipient.send(1); | |
/// check final balance | |
checkBalance(_recipient); | |
/// log everything | |
logTxSenderInfo(); | |
logGasInfo(); | |
// logBalanceInfo(); | |
logBlockInfo(); | |
logCallInfo(msg.sig, msg.value); | |
} | |
/// @dev internal function to check balance for an address and emit log event | |
function checkBalance(address _target) internal returns (uint256) { | |
uint256 balance = address(_target).balance; | |
logBalanceInfo(_target, balance); | |
return balance; | |
} | |
/// @dev lets verify some block hashes against each other on chain | |
function verifyBlockHash(string memory _hash, uint _blockNumber) public returns (bytes32, bytes32) { | |
bytes32 hash1 = keccak256(abi.encodePacked(_hash)); | |
bytes32 hash2 = getBlockHash(_blockNumber); | |
return(hash1, hash2) ; | |
} | |
} | |
contract EventSimulator { | |
/// ERC20 standard compliant Transfer event | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 value | |
); | |
function simulateEvents(address _sender, address _receiver) public { | |
emit Transfer(_sender, _receiver, 1); | |
emit Transfer(_sender, _receiver, 2); | |
emit Transfer(_sender, _receiver, 3); | |
emit Transfer(_sender, _receiver, 4); | |
emit Transfer(_sender, _receiver, 5); | |
emit Transfer(_sender, _receiver, 6); | |
emit Transfer(_sender, _receiver, 7); | |
emit Transfer(_sender, _receiver, 8); | |
emit Transfer(_sender, _receiver, 9); | |
emit Transfer(_sender, _receiver, 10); | |
emit Transfer(_sender, _receiver, 11); | |
emit Transfer(_sender, _receiver, 12); | |
emit Transfer(_sender, _receiver, 13); | |
emit Transfer(_sender, _receiver, 14); | |
emit Transfer(_sender, _receiver, 15); | |
emit Transfer(_sender, _receiver, 16); | |
emit Transfer(_sender, _receiver, 17); | |
emit Transfer(_sender, _receiver, 18); | |
emit Transfer(_sender, _receiver, 19); | |
emit Transfer(_sender, _receiver, 20); | |
emit Transfer(_sender, _receiver, 21); | |
emit Transfer(_sender, _receiver, 22); | |
emit Transfer(_sender, _receiver, 23); | |
emit Transfer(_sender, _receiver, 24); | |
emit Transfer(_sender, _receiver, 25); | |
emit Transfer(_sender, _receiver, 26); | |
emit Transfer(_sender, _receiver, 27); | |
emit Transfer(_sender, _receiver, 28); | |
} | |
} | |
/// @dev now lets try this via a proxy | |
/// @dev creator proxy calls the target function | |
/// @dev same test, same tx.origin, different msg.sender | |
contract CreatorProxy is EventSimulator { | |
address public owner; | |
constructor() public { | |
owner = msg.sender; | |
} | |
/** | |
* @dev calls checkBalanceSendEth() on a target contract | |
* @param _eth_receiver address of the intended recipient of the proxy function call | |
* @param _contract address of the contract to proxy call | |
*/ | |
function proxyCall(address payable _eth_receiver, address payable _contract) public { | |
require(msg.sender == owner, "unauthorized"); | |
TestETL(_contract).checkBalanceSendEth(_eth_receiver); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.0 <0.7.0; | |
library GetCode { | |
function at(address _addr) public view returns (bytes memory o_code) { | |
assembly { | |
// retrieve the size of the code, this needs assembly | |
let size := extcodesize(_addr) | |
// allocate output byte array - this could also be done without assembly | |
// by using o_code = new bytes(size) | |
o_code := mload(0x40) | |
// new "memory end" including padding | |
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) | |
// store length in memory | |
mstore(o_code, size) | |
// actually retrieve the code, this needs assembly | |
extcodecopy(_addr, add(o_code, 0x20), 0, size) | |
} | |
} | |
} | |
contract TestETL { | |
using GetCode for *; | |
address public creator; | |
address public creatorproxy; | |
/** | |
* @dev contructor function which sets creator and creator proxy | |
* @param _proxy address of proxy contract for proxied calls | |
*/ | |
constructor (address _proxy) public { | |
creator = msg.sender; | |
creatorproxy = _proxy; | |
} | |
/// Events to log information cheaply and repeatedly | |
/// msg.sender vs tx.origin log | |
event txSenderInfo(address sender, address origin); | |
/// gas metrics | |
event gasInfo(uint remainingGas, uint txGasPrice, uint blockGasLimit); | |
/// balance details | |
event balanceInfo(address balanceHolder, uint256 balance); | |
/// block details | |
event blockInfo(address coinbase, uint difficulty, uint blockNumber, uint timestamp); | |
/// call details | |
event callInfo(bytes4 msgsig, uint msgvalue); | |
// Fallback function to allow ETH into contract | |
function deposit() public payable { | |
logBlockInfo(); | |
logGasInfo(); | |
logCallInfo(); | |
logTxSenderInfo(); | |
} | |
modifier restricted() { | |
require(msg.sender == creator || msg.sender == creatorproxy, "unauthorized"); | |
_; | |
} | |
function getCode(address _contract) public returns (bytes memory code) { | |
return GetCode.at(_contract); | |
} | |
/** | |
* Helper functions for event emissions | |
*/ | |
/// @dev logs details about the origin of a transaction | |
function logTxSenderInfo() public { | |
emit txSenderInfo(msg.sender, tx.origin); | |
} | |
/// @dev logs the gas, gasprice and block gaslimit | |
function logGasInfo() public { | |
emit gasInfo(msg.gas, tx.gasprice, block.gaslimit); | |
} | |
function logCallInfo() public { | |
emit callInfo(msg.sig, msg.value); | |
} | |
/// @dev logs the coinbase difficulty number and timestamp for the block | |
function logBlockInfo() public { | |
emit blockInfo( | |
block.coinbase, | |
block.difficulty, | |
block.number, | |
block.timestamp | |
); | |
} | |
/// @dev logs the balance for an address | |
function logBalanceInfo(address _balanceHolder, uint256 _balance) public view { | |
emit balanceInfo(_balanceHolder, _balance); | |
} | |
function eventEncode(string memory _forEncoding) public restricted view returns (bytes4) { | |
return bytes4(keccak256(abi.encodePacked(_forEncoding))); | |
} | |
// deprecated in version 0.4.22 and replaced by blockhash(uint blockNumber). | |
function getBlockHash(uint _blockNumber) public restricted returns (bytes32 _hash) { | |
// blockHash() for later versions | |
logBlockInfo(); | |
logGasInfo(); | |
logCallInfo(); | |
logTxSenderInfo(); | |
return block.blockhash(_blockNumber); | |
} | |
/// @dev Test function number 1 | |
function checkBalanceSendEth(address _recipient) public { | |
/// log balance at the start | |
checkBalance(_recipient); | |
/// transfer recipient smallest unit possible | |
_recipient.transfer(1); | |
/// log balance | |
checkBalance(_recipient); | |
/// send recipient smallest unit possible | |
_recipient.send(1); | |
/// check final balance | |
checkBalance(_recipient); | |
/// log everything | |
logTxSenderInfo(); | |
logGasInfo(); | |
// logBalanceInfo(); | |
logBlockInfo(); | |
logCallInfo(); | |
} | |
/// @dev internal function to check balance for an address and emit log event | |
function checkBalance(address _target) internal returns (uint256) { | |
uint256 balance = address(_target).balance; | |
logBalanceInfo(_target, balance); | |
return balance; | |
} | |
/// @dev lets verify some block hashes against each other on chain | |
function verifyBlockHash(string memory _hash, uint _blockNumber) public returns (bytes32, bytes32) { | |
bytes32 hash1 = keccak256(abi.encodePacked(_hash)); | |
bytes32 hash2 = getBlockHash(_blockNumber); | |
return(hash1, hash2) ; | |
} | |
} | |
contract EventSimulator { | |
/// ERC20 standard compliant Transfer event | |
event Transfer( | |
address indexed from, | |
address indexed to, | |
uint256 value | |
); | |
function simulateEvents(address _sender, address _receiver) public { | |
emit Transfer(_sender, _receiver, 1); | |
emit Transfer(_sender, _receiver, 2); | |
emit Transfer(_sender, _receiver, 3); | |
emit Transfer(_sender, _receiver, 4); | |
emit Transfer(_sender, _receiver, 5); | |
emit Transfer(_sender, _receiver, 6); | |
emit Transfer(_sender, _receiver, 7); | |
emit Transfer(_sender, _receiver, 8); | |
emit Transfer(_sender, _receiver, 9); | |
emit Transfer(_sender, _receiver, 10); | |
emit Transfer(_sender, _receiver, 11); | |
emit Transfer(_sender, _receiver, 12); | |
emit Transfer(_sender, _receiver, 13); | |
emit Transfer(_sender, _receiver, 14); | |
emit Transfer(_sender, _receiver, 15); | |
emit Transfer(_sender, _receiver, 16); | |
emit Transfer(_sender, _receiver, 17); | |
emit Transfer(_sender, _receiver, 18); | |
emit Transfer(_sender, _receiver, 19); | |
emit Transfer(_sender, _receiver, 20); | |
emit Transfer(_sender, _receiver, 21); | |
emit Transfer(_sender, _receiver, 22); | |
emit Transfer(_sender, _receiver, 23); | |
emit Transfer(_sender, _receiver, 24); | |
emit Transfer(_sender, _receiver, 25); | |
emit Transfer(_sender, _receiver, 26); | |
emit Transfer(_sender, _receiver, 27); | |
emit Transfer(_sender, _receiver, 28); | |
} | |
} | |
/// @dev now lets try this via a proxy | |
/// @dev creator proxy calls the target function | |
/// @dev same test, same tx.origin, different msg.sender | |
contract CreatorProxy is EventSimulator { | |
address public owner; | |
constructor() public { | |
owner = msg.sender; | |
} | |
/** | |
* @dev calls checkBalanceSendEth() on a target contract | |
* @param _eth_receiver address of the intended recipient of the proxy function call | |
* @param _contract address of the contract to proxy call | |
*/ | |
function proxyCall(address _eth_receiver, address _contract) public { | |
require(msg.sender == owner, "unauthorized"); | |
TestETL(_contract).checkBalanceSendEth(_eth_receiver); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment