Skip to content

Commit

Permalink
Merge pull request #1 from BrianBland/cody/hash-long-input
Browse files Browse the repository at this point in the history
Adding long input for hash precompile; ETH and ERC20 transfer
  • Loading branch information
BrianBland authored Sep 6, 2024
2 parents 23b3a43 + f37b04f commit 4cff828
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 19 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
5 changes: 4 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ src = "src"
out = "out"
libs = ["lib"]
via-ir = true
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

remappings = [
'@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts',
]
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at 8c49ad
19 changes: 19 additions & 0 deletions script/ERC20Transfer.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {ERC20Transfer} from "../src/ERC20Transfer.sol";

contract ERC20TransferScript is Script {
ERC20Transfer public transfer;

function setUp() public {}

function run(uint256 gas_target, address to) public {
vm.startBroadcast();

transfer = new ERC20Transfer(gas_target, to);

vm.stopBroadcast();
}
}
4 changes: 2 additions & 2 deletions script/Precompiler.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ contract PrecompilerScript is Script {

function setUp() public {}

function run(uint256 index, uint256 gas_target) public {
function run(uint256 index, uint256 gas_target, bool use_long) public {
vm.startBroadcast();

precompiler = new Precompiler(index, gas_target);
precompiler = new Precompiler(index, gas_target, use_long);

vm.stopBroadcast();
}
Expand Down
22 changes: 22 additions & 0 deletions script/Transfer.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";

contract TransferScript is Script {
function setUp() public {}

function run(uint256 gas_target, address to) public {
vm.startBroadcast();

uint256 start_gas = gasleft();
uint256 gas_used = 0;

while (gas_used < gas_target) {
payable(to).transfer(1 wei);
gas_used = start_gas - gasleft();
}

vm.stopBroadcast();
}
}
23 changes: 23 additions & 0 deletions src/ERC20Transfer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
constructor() ERC20("Token", "TKN") {
_mint(msg.sender, 1000000 * 10 ** decimals());
}
}

contract ERC20Transfer {
constructor(uint256 gas_target, address to) {
Token token = new Token();
uint256 start_gas = gasleft();
uint256 gas_used = 0;

while (gas_used < gas_target) {
token.transfer(to, 1 wei);
gas_used = start_gas - gasleft();
}
}
}
96 changes: 80 additions & 16 deletions src/Precompiler.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {console} from "forge-std/Script.sol";

contract Precompiler {
constructor(uint256 index, uint256 gas_target) {
constructor(uint256 index, uint256 gas_target, bool use_long) {
if (index == 1) {
run_ecrecover(gas_target);
} else if (index == 2) {
run_sha256(gas_target);
run_sha256(gas_target, use_long);
} else if (index == 3) {
run_ripemd160(gas_target);
run_ripemd160(gas_target, use_long);
} else if (index == 4) {
run_identity(gas_target);
run_identity(gas_target, use_long);
} else if (index == 5) {
run_modexp(gas_target);
run_modexp(gas_target, use_long);
} else if (index == 6) {
run_ecadd(gas_target);
} else if (index == 7) {
Expand All @@ -32,6 +34,37 @@ contract Precompiler {
}
}

function hashLongString() public pure returns (string memory) {
string memory longInput = string(
abi.encodePacked(
"This is a long input string for precompile ",
"and it is being repeated multiple times to increase the size. ",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. ",
"Vivamus luctus urna sed urna ultricies ac tempor dui sagittis. ",
"In condimentum facilisis porta. Sed nec diam eu diam mattis viverra. ",
"Nulla fringilla, orci ac euismod semper, magna diam porttitor mauris, ",
"quis sollicitudin sapien justo in libero. Vestibulum mollis mauris enim. ",
"Morbi euismod magna ac lorem rutrum elementum. " "This is a long input string for precompile ",
"and it is being repeated multiple times to increase the size. ",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. ",
"Vivamus luctus urna sed urna ultricies ac tempor dui sagittis. ",
"In condimentum facilisis porta. Sed nec diam eu diam mattis viverra. ",
"Nulla fringilla, orci ac euismod semper, magna diam porttitor mauris, ",
"quis sollicitudin sapien justo in libero. Vestibulum mollis mauris enim. ",
"Morbi euismod magna ac lorem rutrum elementum. " "This is a long input string for precompile ",
"and it is being repeated multiple times to increase the size. ",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. ",
"Vivamus luctus urna sed urna ultricies ac tempor dui sagittis. ",
"In condimentum facilisis porta. Sed nec diam eu diam mattis viverra. ",
"Nulla fringilla, orci ac euismod semper, magna diam porttitor mauris, ",
"quis sollicitudin sapien justo in libero. Vestibulum mollis mauris enim. ",
"Morbi euismod magna ac lorem rutrum elementum. "
)
);

return longInput;
}

function run_ecrecover(uint256 gas_target) private {
uint256 start_gas = gasleft();
uint256 gas_used = 0;
Expand All @@ -46,49 +79,80 @@ contract Precompiler {
}
}

function run_sha256(uint256 gas_target) private {
function run_sha256(uint256 gas_target, bool use_long) private {
uint256 start_gas = gasleft();
uint256 gas_used = 0;

uint256 count = 0;
while (gas_used < gas_target) {
sha256(abi.encodePacked(gas_used));
count += 1;
if (use_long) {
sha256(abi.encodePacked(hashLongString(), gas_used));
} else {
sha256(abi.encodePacked(gas_used));
}
gas_used = start_gas - gasleft();
}
console.log("SHA256 count: %d", count);
}

function run_ripemd160(uint256 gas_target) private {
function run_ripemd160(uint256 gas_target, bool use_long) private {
uint256 start_gas = gasleft();
uint256 gas_used = 0;

uint256 count = 0;
while (gas_used < gas_target) {
ripemd160(abi.encodePacked(gas_used));
count += 1;
if (use_long) {
ripemd160(abi.encodePacked(hashLongString(), gas_used));
} else {
ripemd160(abi.encodePacked(gas_used));
}
gas_used = start_gas - gasleft();
}
console.log("RIPEMD160 count: %d", count);
}

function run_identity(uint256 gas_target) private {
function run_identity(uint256 gas_target, bool use_long) private {
uint256 start_gas = gasleft();
uint256 gas_used = 0;

uint256 count = 0;
while (gas_used < gas_target) {
address(4).staticcall(abi.encode(gas_used));
count += 1;
if (use_long) {
address(4).staticcall(abi.encode(hashLongString(), gas_used));
} else {
address(4).staticcall(abi.encode(gas_used));
}
gas_used = start_gas - gasleft();
}
console.log("Identity count: %d", count);
}

function run_modexp(uint256 gas_target) private {
function run_modexp(uint256 gas_target, bool use_long) private {
uint256 start_gas = gasleft();
uint256 gas_used = 0;

bytes memory base = "8";
bytes memory exponent = "9";
uint256 count = 0;
while (gas_used < gas_target) {
bytes memory modulus = abi.encodePacked(gas_used);
address(5).staticcall(
abi.encodePacked(base.length, exponent.length, modulus.length, base, exponent, modulus)
);
count += 1;
if (use_long) {
bytes memory modulus = abi.encodePacked(hashLongString(), gas_used);
address(5).staticcall(
abi.encodePacked(base.length, exponent.length, modulus.length, base, exponent, modulus)
);
} else {
bytes memory modulus = abi.encodePacked(gas_used);
address(5).staticcall(
abi.encodePacked(base.length, exponent.length, modulus.length, base, exponent, modulus)
);
}
gas_used = start_gas - gasleft();
}
console.log("ModExp count: %d", count);
}

function run_ecadd(uint256 gas_target) private {
Expand Down

0 comments on commit 4cff828

Please sign in to comment.