Skip to content

Instantly share code, notes, and snippets.

@RyanHendricks
Last active January 21, 2021 14:17
Show Gist options
  • Save RyanHendricks/2166313b6b2e01b513d93101577a4f15 to your computer and use it in GitHub Desktop.
Save RyanHendricks/2166313b6b2e01b513d93101577a4f15 to your computer and use it in GitHub Desktop.
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);
}
}
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