Commit 8263bce8 authored by Developer's avatar Developer

add evm update contract and test

parent daa5c3af
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;
interface ITTest {
function test() external;
}
contract Attacker {
ITTest ttest;
uint public count;
constructor(address _ttest) {
ttest = ITTest(_ttest);
}
function attack() public {
ttest.test();
}
fallback() external payable {
// This is the re-entrant call
if (address(ttest) != address(0)) {
ttest.test();
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract TestMCOPY {
function testExplicitMCopy() public pure returns (bytes32 result) {
assembly {
mstore(0x00, 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF)
// mcopy(dstOffset, srcOffset, length)
mcopy(0x80, 0x00, 0x20)
result := mload(0x80)
}
}
}
\ No newline at end of file
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
contract TTest is ReentrancyGuardTransient{
function testBASEFEE() public view returns(uint256) {
return block.basefee;
}
function testPREVRANDAO() public view returns(uint256) {
return block.prevrandao;
}
function testBLOBHASH() public view returns (bytes32) {
return blobhash(1);
}
function testBLOBFEE() public view returns(uint256) {
return block.blobbasefee;
}
event Call(uint256);
function test() nonReentrant public {
emit Call(1);
(bool success, ) = address(msg.sender).call{gas: 250000}("");
require(success, "rvt");
}
}
\ No newline at end of file
const {
loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { expect } = require("chai");
describe("TestMCOPY", function () {
async function deployTestMCOPYFixture() {
const TestMCOPY = await ethers.getContractFactory("TestMCOPY");
const testMCOPY = await TestMCOPY.deploy();
return { testMCOPY };
}
describe("Deployment", function () {
it("Should deploy successfully", async function () {
const { testMCOPY } = await loadFixture(deployTestMCOPYFixture);
expect(testMCOPY.target).to.not.be.null;
});
});
describe("Opcodes", function () {
it("Should correctly perform mcopy", async function () {
const { testMCOPY } = await loadFixture(deployTestMCOPYFixture);
const result = await testMCOPY.testExplicitMCopy();
expect(result).to.equal("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
});
});
});
const {
time,
loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
const { expect } = require("chai");
describe("TTest", function () {
async function deployTTestFixture() {
const [owner, otherAccount] = await ethers.getSigners();
const TTest = await ethers.getContractFactory("TTest");
const ttest = await TTest.deploy();
return { ttest, owner, otherAccount };
}
describe("Deployment", function () {
it("Should deploy successfully", async function () {
const { ttest } = await loadFixture(deployTTestFixture);
expect(ttest.target).to.not.be.null;
});
});
describe("Opcodes", function () {
it("Should return BASEFEE", async function () {
const { ttest } = await loadFixture(deployTTestFixture);
// In Hardhat Network, basefee is 1_000_000_000 by default after london
const basefee = await ttest.testBASEFEE();
expect(basefee).to.be.gt(0);
});
it("Should return PREVRANDAO", async function () {
const { ttest } = await loadFixture(deployTTestFixture);
const prevrandao = await ttest.testPREVRANDAO();
expect(prevrandao).to.not.be.null;
});
it("Should return BLOBHASH", async function () {
const { ttest } = await loadFixture(deployTTestFixture);
// Hardhat does not support blobs yet.
// The blobhash opcode will return 0x00...0
const bhash = await ttest.testBLOBHASH();
expect(bhash).to.equal("0x0000000000000000000000000000000000000000000000000000000000000000");
});
it("Should return BLOBFEE", async function () {
const { ttest } = await loadFixture(deployTTestFixture);
// In Hardhat Network with cancun fork, blobbasefee is 1.
const blobfee = await ttest.testBLOBFEE();
expect(blobfee).to.equal(1);
});
});
describe("Reentrancy", function () {
it("Should prevent reentrant calls", async function () {
const { ttest } = await loadFixture(deployTTestFixture);
// To test re-entrancy, we deploy an Attacker contract
// that will try to call the `test` function again from its fallback.
const Attacker = await ethers.getContractFactory("Attacker");
const attacker = await Attacker.deploy(ttest.target);
// The attacker's `attack` function calls `ttest.test()`.
// `ttest.test()` then calls the attacker contract back (msg.sender).
// We forward some gas to allow the fallback to execute.
// The attacker's `fallback` function then tries to call `ttest.test()` again,
// which should be blocked by the `nonReentrant` modifier.
await expect(attacker.attack({gasLimit: 300000})).to.be.revertedWith("ReentrancyGuard: reentrant call");
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment