Commit 767dbf36 authored by Developer's avatar Developer

update

parent 4c71963d
File added
#DEPLOY_PRIVATE_KEY=0x59a4fbbeb5df606612f8c5ad298483646a42b232b1184b7f54607e1a5ea13284
# mova network
#DEPLOY_PRIVATE_KEY=0xca8bdd675179e7411b74518fe8a5f0691ff1edcc435a5d92402e2efe5dcd3a0c
DEPLOY_PRIVATE_KEY=0x2c131e5855e9005a1b42837a54f0033191cb53eb243217e95b360b4c4a2bf4f9
# mova testnet genesis account
#DEPLOY_PRIVATE_KEY=0x8a35953f17f8109020c09a95963aea73b34e5f02d31451ce91fd4d8380476730
# apolo 0x119BA92c15337FfB37871e44F3f9102409D95F12
#DEPLOY_PRIVATE_KEY=0x0a5dc451f7c8ce153e0aa1cccfd9c0dc21f4bb67d15f5f92e9162e4df99dd92d
# mova bitheart.org
#DEPLOY_PRIVATE_KEY=0x7d1d4ad0827d007aea8001ef205549bb054e90876337f6f1667b93a952d1f34c
#DEPLOY_PRIVATE_KEY=0x2aeab02a323f49acb0346852958a76fb6d94539ad322151b8472329adea5db4d
#DEPLOY_PRIVATE_KEY=0x3b62ea39e3751c489fa1965fee80cff1546a9179821c3d34d9b3f3fbfafb3924
NAME_SIGNER_KEY=0x3b62ea39e3751c489fa1965fee80cff1546a9179821c3d34d9b3f3fbfafb3924
# bridge envrionment
TREASURY_ADDRESS=""
BRIDGE_VALIDATORS="0x00008B378851EBa80F66575B2fBC34e9e0b7BAa7,0x014702f872C1E0A7314a8D25aC1034257F28BBf5"
// 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.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/// @notice ComplexToken - a feature-rich token used for stress-testing nodes.
/// Features:
/// - ERC20 + EIP-2612 permit
/// - Pausable (owner)
/// - Snapshot (owner)
/// - Batch transfer
/// - Transfer fee with optional fee recipient
/// - Simple staking: deposit/withdraw with rewards accrual
/// - reentrancy protection on stateful flows
contract ComplexToken is ERC20, ERC20Permit, Ownable {
// fee in basis points (parts per 10,000)
uint16 public feeBps;
address public feeRecipient;
// staking
mapping(address => uint256) private _stakes;
mapping(address => uint256) private _stakeRewards; // accumulated rewards in token units
uint256 public totalStaked;
uint256 public rewardRatePerSecond = 1e15; // 0.001 token per second per staked token unit scaled (simple)
event BatchTransfer(address indexed sender, uint256 count);
event FeeChanged(uint16 newFeeBps, address newRecipient);
event Staked(address indexed user, uint256 amount);
event Unstaked(address indexed user, uint256 amount);
event RewardsClaimed(address indexed user, uint256 amount);
constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) ERC20Permit(name_) Ownable(msg.sender) {
feeBps = 0;
feeRecipient = owner();
// mint some initial supply to owner for testing convenience
_mint(msg.sender, 1_000_000 * (10 ** decimals()));
}
function setFee(uint16 _feeBps, address _recipient) external onlyOwner {
require(_feeBps <= 1000, "fee too high"); // max 10%
feeBps = _feeBps;
feeRecipient = _recipient;
emit FeeChanged(_feeBps, _recipient);
}
// -------------------- Transfer logic with fee --------------------
// function _transfer(address sender, address recipient, uint256 amount) internal virtual override {
// if (feeBps == 0 || sender == feeRecipient || recipient == feeRecipient) {
// super._transfer(sender, recipient, amount);
// return;
// }
//
// uint256 fee = (amount * feeBps) / 10000;
// uint256 amountAfter = amount - fee;
// if (fee > 0) {
// super._transfer(sender, feeRecipient, fee);
// }
// super._transfer(sender, recipient, amountAfter);
// }
// -------------------- Batch transfer --------------------
/// @notice transfer to multiple recipients in one call
/// @param recipients array of recipient addresses
/// @param amounts array of amounts matching recipients
function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) public {
require(recipients.length == amounts.length, "len mismatch");
uint256 len = recipients.length;
for (uint256 i = 0; i < len; ++i) {
_transfer(msg.sender, recipients[i], amounts[i]);
}
emit BatchTransfer(msg.sender, len);
}
// -------------------- Simple staking --------------------
/// @notice deposit tokens to stake
function stake(uint256 amount) external {
require(amount > 0, "zero");
_updateRewards(msg.sender);
_transfer(msg.sender, address(this), amount);
_stakes[msg.sender] += amount;
totalStaked += amount;
emit Staked(msg.sender, amount);
}
/// @notice withdraw staked tokens (claims rewards as well)
function unstake(uint256 amount) external {
require(amount > 0, "zero");
uint256 staked = _stakes[msg.sender];
require(staked >= amount, "insufficient stake");
_updateRewards(msg.sender);
_stakes[msg.sender] = staked - amount;
totalStaked -= amount;
_transfer(address(this), msg.sender, amount);
emit Unstaked(msg.sender, amount);
}
/// @notice claim staking rewards
function claimRewards() external {
_updateRewards(msg.sender);
uint256 reward = _stakeRewards[msg.sender];
require(reward > 0, "no rewards");
_stakeRewards[msg.sender] = 0;
_transfer(address(this), msg.sender, reward);
emit RewardsClaimed(msg.sender, reward);
}
function stakeOf(address account) external view returns (uint256) {
return _stakes[account];
}
function pendingRewards(address account) external view returns (uint256) {
// approximate using stored rewards + accrued since last update
uint256 base = _stakeRewards[account];
uint256 staked = _stakes[account];
if (staked == 0) return base;
// simplistic accrual: rewardRatePerSecond * staked * elapsed / 1e18
// we don't store lastUpdate timestamps per account here to keep contract simpler for stress testing
return base; // accurate only after _updateRewards
}
// internal helper: naive reward accrual per call
function _updateRewards(address account) internal {
// For stress testing we do a cheap deterministic increment based on block.timestamp
// This is intentionally naive: on each interaction we add a small fixed reward proportional to stake.
uint256 staked = _stakes[account];
if (staked == 0) return;
// reward = staked * rewardRatePerSecond (scaled) / 1e18
// to avoid tiny fractions and complexity, compute as (staked * rewardRatePerSecond) / 1e18
uint256 reward = (staked * rewardRatePerSecond) / 1e18;
if (reward > 0) {
// mint rewards to contract balance if needed
_mint(address(this), reward);
_stakeRewards[account] += reward;
}
}
// -------------------- Utility heavy function (complex state changes) --------------------
/// @notice heavyOperation performs multiple transfers, burns, and mints in a single call to exercise node state changes
function heavyOperation(address[] calldata targets, uint256[] calldata amounts) external {
require(targets.length == amounts.length, "len mismatch");
uint256 len = targets.length;
for (uint256 i = 0; i < len; ++i) {
address to = targets[i];
uint256 amt = amounts[i];
if (amt == 0) continue;
// transfer a portion to target
uint256 part = amt / 2;
_transfer(msg.sender, to, part);
// burn a small part
uint256 burnAmt = amt / 10;
if (burnAmt > 0) _burn(msg.sender, burnAmt);
// mint a tiny reward to target
uint256 mintAmt = amt / 100;
if (mintAmt > 0) _mint(to, mintAmt);
}
}
// -------------------- Allow contract to receive ETH (for advanced tests) --------------------
receive() external payable {}
// Fallback to accept arbitrary calls
fallback() external payable {}
}
// filepath: /Users/luxq/work/wuban/testcontract/contracts/Distributor.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
/// @title Distributor - generate 700 pseudo-random addresses and distribute ETH to them
contract Distributor {
address[] public recipients;
uint256 public constant RECIPIENT_COUNT = 700;
/// @notice Construct the contract and generate RECIPIENT_COUNT addresses from a seed
/// @param seed A user provided seed to influence address generation (can be 0)
constructor(bytes32 seed) {
// generate deterministic pseudo-random addresses using keccak256 of seed, block timestamp and index
// Note: these are not real externally-owned accounts with known private keys — they are just 20-byte addresses
// and may be inaccessible if nobody controls the corresponding private key. Use for testing/stress only.
recipients = new address[](RECIPIENT_COUNT);
for (uint256 i = 0; i < RECIPIENT_COUNT; ++i) {
// mix seed with block.timestamp and sender to get some variability
bytes32 h = keccak256(abi.encodePacked(seed, block.timestamp, msg.sender, i));
// take the lower 160 bits as an address
recipients[i] = address(uint160(uint256(h)));
}
}
/// @notice Get the number of recipients
function recipientsCount() external pure returns (uint256) {
return RECIPIENT_COUNT;
}
/// @notice Distribute msg.value equally to all recipients.
/// @dev This will attempt RECIPIENT_COUNT transfers in a single transaction and may run out of gas.
/// It's provided for convenience, but prefer `distributeRange` with smaller ranges for production use.
function distributeAll() external payable {
uint256 total = msg.value;
require(total > 0, "No ETH provided");
uint256 per = total / RECIPIENT_COUNT;
require(per > 0, "Amount too small for equal distribution");
for (uint256 i = 0; i < RECIPIENT_COUNT; ++i) {
// use call to forward gas and avoid 2300 stipend issues
(bool success, ) = recipients[i].call{value: per}("");
// do not revert on single failure to maximize distribution; failed transfers keep funds in contract
if (!success) {
// continue; failed amount stays in contract
}
}
// refund any leftover (due to integer division or failed sends) back to sender
uint256 leftover = address(this).balance;
if (leftover > 0) {
payable(msg.sender).transfer(leftover);
}
}
/// @notice Distribute `amountPer` wei to each recipient in the half-open range [start, end)
/// @param start The starting index (inclusive)
/// @param end The end index (exclusive)
/// @param amountPer Amount in wei to send to each recipient in the range
function distributeRange(uint256 start, uint256 end, uint256 amountPer) external payable {
require(start < end && end <= RECIPIENT_COUNT, "Invalid range");
uint256 count = end - start;
uint256 required = count * amountPer;
require(msg.value >= required, "Insufficient ETH provided");
for (uint256 i = start; i < end; ++i) {
(bool success, ) = recipients[i].call{value: amountPer}("");
if (!success) {
// on failure, don't revert — leave failed amount in contract
}
}
// refund any extra wei back to sender
uint256 leftover = address(this).balance;
if (leftover > 0) {
payable(msg.sender).transfer(leftover);
}
}
/// @notice Return a copy of recipients (careful: large array)
function getRecipients() external view returns (address[] memory) {
return recipients;
}
// Allow the contract to receive ETH
receive() external payable {}
}
This diff is collapsed.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
/// @title Multicall3
/// @notice Aggregate results from multiple function calls
/// @dev Multicall & Multicall2 backwards-compatible
/// @dev Aggregate methods are marked `payable` to save 24 gas per call
/// @author Michael Elliot <mike@makerdao.com>
/// @author Joshua Levine <joshua@makerdao.com>
/// @author Nick Johnson <arachnid@notdot.net>
/// @author Andreas Bigger <andreas@nascent.xyz>
/// @author Matt Solomon <matt@mattsolomon.dev>
contract Multicall3 {
struct Call {
address target;
bytes callData;
}
struct Call3 {
address target;
bool allowFailure;
bytes callData;
}
struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
/// @notice Backwards-compatible call aggregation with Multicall
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return returnData An array of bytes containing the responses
function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {
blockNumber = block.number;
uint256 length = calls.length;
returnData = new bytes[](length);
Call calldata call;
for (uint256 i = 0; i < length;) {
bool success;
call = calls[i];
(success, returnData[i]) = call.target.call(call.callData);
require(success, "Multicall3: call failed");
unchecked { ++i; }
}
}
/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls without requiring success
/// @param requireSuccess If true, require all calls to succeed
/// @param calls An array of Call structs
/// @return returnData An array of Result structs
function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {
uint256 length = calls.length;
returnData = new Result[](length);
Call calldata call;
for (uint256 i = 0; i < length;) {
Result memory result = returnData[i];
call = calls[i];
(result.success, result.returnData) = call.target.call(call.callData);
if (requireSuccess) require(result.success, "Multicall3: call failed");
unchecked { ++i; }
}
}
/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls and allow failures using tryAggregate
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return blockHash The hash of the block where the calls were executed
/// @return returnData An array of Result structs
function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
blockNumber = block.number;
blockHash = blockhash(block.number);
returnData = tryAggregate(requireSuccess, calls);
}
/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls and allow failures using tryAggregate
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return blockHash The hash of the block where the calls were executed
/// @return returnData An array of Result structs
function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
(blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
}
/// @notice Aggregate calls, ensuring each returns success if required
/// @param calls An array of Call3 structs
/// @return returnData An array of Result structs
function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {
uint256 length = calls.length;
returnData = new Result[](length);
Call3 calldata calli;
for (uint256 i = 0; i < length;) {
Result memory result = returnData[i];
calli = calls[i];
(result.success, result.returnData) = calli.target.call(calli.callData);
assembly {
// Revert if the call fails and failure is not allowed
// `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
// set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// set data offset
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// set length of revert string
mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
// set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
revert(0x00, 0x64)
}
}
unchecked { ++i; }
}
}
/// @notice Aggregate calls with a msg value
/// @notice Reverts if msg.value is less than the sum of the call values
/// @param calls An array of Call3Value structs
/// @return returnData An array of Result structs
function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {
uint256 valAccumulator;
uint256 length = calls.length;
returnData = new Result[](length);
Call3Value calldata calli;
for (uint256 i = 0; i < length;) {
Result memory result = returnData[i];
calli = calls[i];
uint256 val = calli.value;
// Humanity will be a Type V Kardashev Civilization before this overflows - andreas
// ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256
unchecked { valAccumulator += val; }
(result.success, result.returnData) = calli.target.call{value: val}(calli.callData);
assembly {
// Revert if the call fails and failure is not allowed
// `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
// set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// set data offset
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// set length of revert string
mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
// set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
revert(0x00, 0x84)
}
}
unchecked { ++i; }
}
// Finally, make sure the msg.value = SUM(call[0...i].value)
require(msg.value == valAccumulator, "Multicall3: value mismatch");
}
/// @notice Returns the block hash for the given block number
/// @param blockNumber The block number
function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
blockHash = blockhash(blockNumber);
}
/// @notice Returns the block number
function getBlockNumber() public view returns (uint256 blockNumber) {
blockNumber = block.number;
}
/// @notice Returns the block coinbase
function getCurrentBlockCoinbase() public view returns (address coinbase) {
coinbase = block.coinbase;
}
/// @notice Returns the block difficulty
function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
difficulty = block.difficulty;
}
/// @notice Returns the block gas limit
function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
gaslimit = block.gaslimit;
}
/// @notice Returns the block timestamp
function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
timestamp = block.timestamp;
}
/// @notice Returns the (ETH) balance of a given address
function getEthBalance(address addr) public view returns (uint256 balance) {
balance = addr.balance;
}
/// @notice Returns the block hash of the last block
function getLastBlockHash() public view returns (bytes32 blockHash) {
unchecked {
blockHash = blockhash(block.number - 1);
}
}
/// @notice Gets the base fee of the given block
/// @notice Can revert if the BASEFEE opcode is not implemented by the given chain
function getBasefee() public view returns (uint256 basefee) {
basefee = block.basefee;
}
/// @notice Returns the chain id
function getChainId() public view returns (uint256 chainid) {
chainid = block.chainid;
}
}
\ No newline at end of file
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;
contract WMDD {
string public name = "Wrapped MMDD";
string public symbol = "MMDD";
uint8 public decimals = 18;
event Approval(address indexed src, address indexed guy, uint wad);
event Transfer(address indexed src, address indexed dst, uint wad);
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
// 接收以太币
receive() external payable {
deposit();
}
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint wad) public {
require(balanceOf[msg.sender] >= wad, "Insufficient balance");
balanceOf[msg.sender] -= wad;
// 使用 call 发送以太币
(bool success, ) = msg.sender.call{value: wad}("");
require(success, "Transfer failed");
emit Withdrawal(msg.sender, wad);
}
function totalSupply() public view returns (uint) {
return address(this).balance;
}
function approve(address guy, uint wad) public returns (bool) {
allowance[msg.sender][guy] = wad;
emit Approval(msg.sender, guy, wad);
return true;
}
function transfer(address dst, uint wad) public returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint wad) public returns (bool) {
require(balanceOf[src] >= wad, "Insufficient balance");
if (src != msg.sender && allowance[src][msg.sender] != type(uint).max) {
require(allowance[src][msg.sender] >= wad, "Allowance exceeded");
allowance[src][msg.sender] -= wad;
}
balanceOf[src] -= wad;
balanceOf[dst] += wad;
emit Transfer(src, dst, wad);
return true;
}
}
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
contract BlockInfo {
uint256 blockheight = 0;
uint256 blocktime = 0;
function setBlockInfo() public {
blockheight = block.number;
blocktime = block.timestamp;
}
function getBlockInfo() public view returns (uint256, uint256) {
return (blockheight, blocktime);
}
}
\ No newline at end of file
This diff is collapsed.
// 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
pragma solidity >=0.5.0;
pragma experimental ABIEncoderV2;
/// @title Multicall2 - Aggregate results from multiple read-only function calls
/// @author Michael Elliot <mike@makerdao.com>
/// @author Joshua Levine <joshua@makerdao.com>
/// @author Nick Johnson <arachnid@notdot.net>
contract Multicall2 {
struct Call {
address target;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {
blockNumber = block.number;
returnData = new bytes[](calls.length);
for(uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
require(success, "Multicall aggregate: call failed");
returnData[i] = ret;
}
}
function blockAndAggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
(blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
}
function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
blockHash = blockhash(blockNumber);
}
function getBlockNumber() public view returns (uint256 blockNumber) {
blockNumber = block.number;
}
function getCurrentBlockCoinbase() public view returns (address coinbase) {
coinbase = block.coinbase;
}
function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
difficulty = block.difficulty;
}
function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
gaslimit = block.gaslimit;
}
function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
timestamp = block.timestamp;
}
function getEthBalance(address addr) public view returns (uint256 balance) {
balance = addr.balance;
}
function getLastBlockHash() public view returns (bytes32 blockHash) {
blockHash = blockhash(block.number - 1);
}
function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) {
returnData = new Result[](calls.length);
for(uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
if (requireSuccess) {
require(success, "Multicall2 aggregate: call failed");
}
returnData[i] = Result(success, ret);
}
}
function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
blockNumber = block.number;
blockHash = blockhash(block.number);
returnData = tryAggregate(requireSuccess, calls);
}
}
\ 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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract RevertContract {
event log(string message);
modifier minimumEther(uint256 _amount) {
require(_amount >= 1*10**18, "minimum 1 ether");
_;
}
function sendViaTransfer(address payable _to, uint256 _amount) public payable minimumEther(_amount) {
require(_amount >= 1*10**18, "minimum 1 ether");
_to.transfer(_amount);
}
function sendViaSend(address payable _to, uint256 _amount) public payable minimumEther(_amount) returns (bool) {
emit log("sendViaSend");
bool sent = _to.send(_amount);
require(sent, "Send failed");
return sent;
}
function sendViaCall(address payable _to, uint256 _amount) public payable minimumEther(_amount) returns (bool) {
emit log("sendViaCall");
(bool success, ) = _to.call{value: _amount}("");
require(success, "Call failed");
return success;
}
receive() external payable {}
}
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract TestToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
_mint(msg.sender, 1000000000 * 10 ** decimals());
}
function burn(uint256 amount) public {
_burn(msg.sender, amount);
}
}
\ No newline at end of file
This diff is collapsed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
......
......@@ -33,27 +33,7 @@ const accounts = { mnemonic }
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
evmVersion: "istanbul",
compilers: [
{
version: "0.8.26",
settings: {
evmVersion: "cancun",
optimizer: {
enabled: true,
runs: 200,
},
},
},
{
version: "0.8.24",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
{
version: "0.8.20",
settings: {
......@@ -64,7 +44,7 @@ module.exports = {
},
},
{
version: "0.8.10",
version: "0.8.12",
settings: {
optimizer: {
enabled: true,
......@@ -122,10 +102,15 @@ module.exports = {
},
networks: {
hardhat: {
hardfork: "cancun",
accounts: [{ privateKey, balance: "10000000000000000000000" }], // Example balance
gas: 10000000,
gasPrice: 10000000000
},
bsc: {
url: "https://bsc-dataseed.bnbchain.org",
accounts: [privateKey]
},
hole: {
url: "https://rpc.hole.bitheart.org",
accounts: [privateKey]
......@@ -134,8 +119,64 @@ module.exports = {
url: "https://rpc.mova.bitheart.org",
accounts: [privateKey]
},
usd1: {
url: "https://rpc.usd1swap.ai",
accounts: [privateKey]
},
mova: {
url: "https://mars.rpc.movachain.com",
url: "https://rpc2.movachain.com",
accounts: [privateKey]
},
movamainnet: {
url: "https://rpc.movachain.com",
accounts: [privateKey]
},
remote: {
url: "http://13.212.120.130:8545",
accounts: [privateKey]
},
a: {
url:"https://1.r.movax.ai",
accounts: [privateKey]
},
b: {
url:"https://2.r.movax.ai",
accounts: [privateKey]
},
c: {
url:"https://3.r.movax.ai",
accounts: [privateKey]
},
d: {
url:"https://4.r.movax.ai",
accounts: [privateKey]
},
e: {
url:"https://5.r.movax.ai",
accounts: [privateKey]
},
n: {
url: "https://a.r.movax.ai",
accounts: [privateKey]
},
m7: {
url: "https://7.r.movax.ai",
accounts: [privateKey]
},
m8: {
url: "https://8.r.movax.ai",
accounts: [privateKey]
},
m9: {
url: "https://9.r.movax.ai",
accounts: [privateKey]
},
m10: {
url: "https://10.r.movax.ai",
accounts: [privateKey]
},
fork: {
url: "http://13.213.53.205:8545",
accounts: [privateKey]
}
},
......
#!/bin/bash
# check an file is exist at the path
if [ -f "/data/chains/rococo_local_testnet/network/secret_ed25519" ]; then
echo "Secret key already exists, skipping generation."
else
/usr/bin/polkadot generate-node-key --base-path /data --chain /app/rococo-local.json
fi
/usr/bin/polkadot --base-path=/data --chain=/app/rococo-local.json --validator --rpc-external --rpc-cors=all --name=$NODEROLE --$NODEROLE --rpc-methods=unsafe --force-authoring
\ No newline at end of file
This diff is collapsed.
......@@ -4,12 +4,16 @@
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "cross-env NODE_ENV=test mocha --exit --recursive --timeout 20000"
},
"private": true,
"devDependencies": {
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"hardhat": "^2.24.0"
"hardhat": "^2.24.0",
"mocha": "^10.2.0",
"chai": "^4.3.7",
"ethers": "^6.9.0",
"cross-env": "^7.0.3"
},
"dependencies": {
"@openzeppelin/contracts": "^5.3.0",
......
const hre = require("hardhat");
async function main() {
const blockContract = await hre.ethers.getContractFactory("BlockInfo");
const contract = await blockContract.deploy();
await contract.waitForDeployment();
const contractAddr = await contract.getAddress();
console.log("BlockInfo Contract deployed at:", contractAddr);
// setBlockInfo
const tx = await contract.setBlockInfo();
await tx.wait();
console.log("Block info set.");
// getBlockInfo
const info = await contract.getBlockInfo();
const [blockheight, blocktime] = info;
console.log("Retrieved Block Info:", blockheight.toString(), blocktime.toString());
let rpcBlockHeader = await hre.ethers.provider.getBlock(blockheight);
if (blocktime != rpcBlockHeader.timestamp) {
console.error("Block time mismatch!", blocktime.toString(), rpcBlockHeader.timestamp.toString());
} else {
console.log("Block time matches.");
}
console.log("RPC Block Info:", rpcBlockHeader.number.toString(), rpcBlockHeader.timestamp.toString());
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
let initialValidators = process.env.BRIDGE_VALIDATORS
async function addValidators(contract, validators) {
let validatorList = validators.split(',')
for (let i = 0; i < validatorList.length; i++) {
var tx = await contract.addValidator(validatorList[i])
await tx.wait();
console.log("Added validator:", validatorList[i]);
}
}
// Define the script
async function deployAtSourceChain() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"Bridge"
);
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed for source at:", depAddr);
await initForSourceChain(contract);
}
async function initForSourceChain(bridge) {
// add validator
await addValidators(bridge, initialValidators);
// set
}
async function deployAtMovaChain() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"Bridge"
);
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed for mova at:", depAddr);
await initForMovaChain(contract);
}
async function initForMovaChain(bridge) {
await addValidators(bridge, initialValidators);
}
// Define the script
async function main() {
await deployAtSourceChain();
await deployAtMovaChain();
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
var addrlist = [
"0xaccf7aacd00bb765120f10685e58d916d3ec3057",
"0x4631638617F6CF476BeC1AA9A892D308AaE2062A",
"0x43Fa8B58AaBeF30bE4221C7c435Fa38d34f0ccb1",
"0x193b7fBA150679AC96c675964180dA078B73fE3c",
"0x5b89a423416B00769ecB9F148411CD686d165A43",
"0xDF2cf3eE3E4E36490F5f942372fF4c975040bBd0",
"0xdD9720aBe15CD07cc2BF9213C1f08CFf1AE0b37D",
"0xD7FB4128F5451f88A5e525ef5303d714633435A7",
"0xf5c5C8cC784C8183316f4d1f0E50c46DF45920c8",
"0x9923f67774A4250bf2B2eA34Da9cBbc6aBd98caD",
"0xe40701772cCBA7a515CE557c3eaeB4B29B92C71e"
]
async function test() {
for (let i = 0; i < addrlist.length; i++) {
const balance = await hre.ethers.provider.getBalance(addrlist[i]);
console.log("Address:", addrlist[i], " Balance:", hre.ethers.formatEther(balance), " ETH");
}
}
// Define the script
async function main() {
await test()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory, ethers} = require("ethers");
const hre = require("hardhat");
// Define the script
async function main() {
const factoryAddress = '0xedd8Da22D948f3F594FdC37840d961461814EeA3'
const bytecode = await hre.ethers.provider.getCode(factoryAddress)
const codeHash = hre.ethers.keccak256(bytecode);
console.log('Factory Code Hash:', codeHash);
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const hre = require("hardhat");
// implement a script that only estimates gas for sending token to a list of users.
async function estimateTokenTransferGas(tokenContract, to, amount) {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
// Encode the function call
const abi = [
"function transfer(address to, uint256 amount) external returns (bool)"
];
const iface = new hre.ethers.Interface(abi);
const data = iface.encodeFunctionData("transfer", [to, amount]);
// Estimate gas
try {
const gasEstimate = await hre.ethers.provider.estimateGas({
from: signer.address,
to: tokenContract,
data: data,
value: 0,
});
console.log(`Estimated gas for transferring ${hre.ethers.formatEther(amount)} tokens to ${to}: ${gasEstimate.toString()} gas`);
} catch (e) {
console.error(`Error estimating gas for transferring to ${to}:`, e);
}
}
async function tokenInfo(tokenContract) {
const abi = [
"function name() view returns (string)",
"function symbol() view returns (string)",
"function totalSupply() view returns (uint256)",
"function decimals() view returns (uint8)"
];
const iface = new hre.ethers.Interface(abi);
const nameData = iface.encodeFunctionData("name", []);
const symbolData = iface.encodeFunctionData("symbol", []);
const totalSupplyData = iface.encodeFunctionData("totalSupply", []);
const decimalsData = iface.encodeFunctionData("decimals", []);
const nameResult = await hre.ethers.provider.call({
to: tokenContract,
data: nameData
});
const symbolResult = await hre.ethers.provider.call({
to: tokenContract,
data: symbolData
});
const totalSupplyResult = await hre.ethers.provider.call({
to: tokenContract,
data: totalSupplyData
});
const decimalsResult = await hre.ethers.provider.call({
to: tokenContract,
data: decimalsData
});
const name = iface.decodeFunctionResult("name", nameResult)[0];
const symbol = iface.decodeFunctionResult("symbol", symbolResult)[0];
const totalSupply = iface.decodeFunctionResult("totalSupply", totalSupplyResult)[0];
const decimals = iface.decodeFunctionResult("decimals", decimalsResult)[0];
console.log(`Token Info - Name: ${name}, Symbol: ${symbol}, Total Supply: ${hre.ethers.formatUnits(totalSupply, decimals)}, Decimals: ${decimals}`);
}
async function main() {
// const tokenContract = await hre.ethers.getContractAt("PublicToken", '')
let tokenAddr = '0x6Cd7919B80a9cFc8d2C6cfa363aF70040a48F10E';
// List of users to estimate gas for
const users = [
"0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2",
"0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db",
"0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB"
];
let amount = hre.ethers.parseEther("0.00001");
// Estimate gas for each user
for (let i = 0; i < 3; i++) {
let idx = i % users.length;
let user = users[idx];
await estimateTokenTransferGas(tokenAddr, user, amount);
// sleep 1s
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Get token info
await tokenInfo(tokenAddr);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function forceRevert() {
// 部署合约
const factory = await hre.ethers.getContractFactory("RevertContract");
const contract = await factory.deploy();
await contract.waitForDeployment();
const contractAddress = await contract.getAddress();
console.log("Contract deployed at:", contractAddress);
return
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const transferAmount = hre.ethers.parseEther("0.0005"); // 小于 1 ETH
var nonce = await hre.ethers.provider.getTransactionCount(signer.address)
const chainid = await hre.ethers.provider.getNetwork().then(network => network.chainId);
// Encode the function call
const abi = ["function sendViaTransfer(address payable _to, uint256 _amount)"];
const iface = new hre.ethers.Interface(abi);
const data = iface.encodeFunctionData("sendViaTransfer", ['0xAD4143Df8Fe9E31B1C4318e8dE555872085f481d', transferAmount]);
// 签名交易
const signedTx = await signer.signTransaction({
type: 0,
chainId: chainid,
nonce: nonce,
to: contractAddress,
data: data,
value: transferAmount,
gasLimit: 1000000, // 设置 gas 限制
gasPrice: hre.ethers.parseUnits("1", "gwei"), // 设置 gas 价格
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent:", txResponse.hash);
}
// Define the script
async function main() {
await forceRevert()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function forceRevert() {
// 部署合约
const factory = await hre.ethers.getContractFactory("RevertContract");
const contract = await factory.deploy();
await contract.waitForDeployment();
const contractAddress = await contract.getAddress();
console.log("Contract deployed at:", contractAddress);
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const transferAmount = hre.ethers.parseEther("1"); // 小于 1 ETH
var nonce = await hre.ethers.provider.getTransactionCount(signer.address)
const chainid = await hre.ethers.provider.getNetwork().then(network => network.chainId);
// Encode the function call
const abi = ["function sendViaTransfer(address payable _to, uint256 _amount)"];
const iface = new hre.ethers.Interface(abi);
const data = iface.encodeFunctionData("sendViaTransfer", ['0xAD4143Df8Fe9E31B1C4318e8dE555872085f481d', transferAmount]);
var balance = await hre.ethers.provider.getBalance(signer.address);
console.log("Sender balance:", hre.ethers.formatEther(balance), " ETH");
// 签名交易
const signedTx = await signer.signTransaction({
type: 0,
chainId: chainid,
nonce: nonce,
to: contractAddress,
data: data,
value: transferAmount,
gasLimit: 1000000, // 设置 gas 限制
gasPrice: hre.ethers.parseUnits("10000", "gwei"), // 设置 gas 价格
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent:", txResponse.hash);
// wait receipt
const receipt = await txResponse.wait();
console.log("Transaction receipt:", receipt);
balance = await hre.ethers.provider.getBalance(signer.address);
console.log("Sender balance:", hre.ethers.formatEther(balance), " ETH");
}
// Define the script
async function main() {
await forceRevert()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const hre = require("hardhat");
async function coinBalance(userlist) {
let height = await hre.ethers.provider.getBlockNumber();
console.log(`Current block height: ${height}`);
for (let i = 0; i < userlist.length; i++) {
let user = userlist[i];
let balance = await hre.ethers.provider.getBalance(user);
console.log(`MOVA balance of ${user}: ${hre.ethers.formatEther(balance)} ETH`);
}
}
async function tokenBalance(tokenAddr, userlist) {
const tokenContract = await hre.ethers.getContractAt("PublicToken", tokenAddr);
for (let i = 0; i < userlist.length; i++) {
let user = userlist[i];
let balance = await tokenContract.balanceOf(user);
console.log(`Token balance of ${user}: ${hre.ethers.formatEther(balance)} tokens`);
}
}
async function deployToken() {
const tokenFactory = await hre.ethers.getContractFactory(
"PublicToken"
);
const tokenContract = await tokenFactory.deploy();
await tokenContract.waitForDeployment();
const tokenAddr = await tokenContract.getAddress();
console.log("Token Contract deployed at:", tokenAddr);
return tokenAddr;
}
async function sendCoin(to, nonce) {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const transferAmount = hre.ethers.parseEther("0.0001");
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
const signedTx = await signer.signTransaction({
type: 0,
chainId: chainId,
nonce: nonce,
to: to,
data: '',
value: transferAmount,
gasLimit: 1000000,
gasPrice: hre.ethers.parseUnits("1", "gwei"),
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction coin sent:", txResponse.hash);
}
async function sendToken(tokenContract, to, amount, nonce) {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const chainid = await hre.ethers.provider.getNetwork().then(network => network.chainId);
// Encode the function call
const abi = [
"function mint(address to, uint256 amount) external"
];
const iface = new hre.ethers.Interface(abi);
const data = iface.encodeFunctionData("mint", [to, amount]);
// 签名交易
const signedTx = await signer.signTransaction({
type: 0,
chainId: chainid,
nonce: nonce,
to: tokenContract,
data: data,
value: 0,
gasLimit: 1000000, // 设置 gas 限制
gasPrice: hre.ethers.parseUnits("1", "gwei"),
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction token sent:", txResponse.hash);
}
// Define the script
async function main() {
const tokenFactory = await hre.ethers.getContractFactory(
"PublicToken"
);
const tokenContract = await tokenFactory.deploy();
await tokenContract.waitForDeployment();
const tokenAddr = await tokenContract.getAddress();
console.log("Token Contract deployed at:", tokenAddr);
// loop transfer token and eth to multiple users
const accounts = await hre.ethers.getSigners();
const sender = accounts[0];
const users = [
'0xF26B752d804F14f863462f310e0b01B38fFD414e',
'0x6ddb3A03366e218956483A840D8BfB490ADE1beB',
'0x9a0782a52460B7ac7f0FbEc3756BFD58eD63C2a3'
];
let sendernonce = await hre.ethers.provider.getTransactionCount(sender.address);
for (let i = 0; i < 10000; i++) {
let idx = i % users.length;
let user = users[idx];
// build tx with all param and sign tx with sender private key
// transfer 0.05 MOVA to user
await sendCoin(user, sendernonce);
sendernonce+=1;
await sendToken(tokenAddr, user, hre.ethers.parseEther("100.0"), sendernonce);
sendernonce +=1;
// sleep 1s.
await new Promise(resolve => setTimeout(resolve, 1000));
}
// await coinBalance(['0x9a0782a52460B7ac7f0FbEc3756BFD58eD63C2a3','0x6ddb3A03366e218956483A840D8BfB490ADE1beB'])
// await tokenBalance('0x57B84A31E00eF4378E6b2D30703b73d02Aee13f8', ['0xF26B752d804F14f863462f310e0b01B38fFD414e'])
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
// Define the script
async function main() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"HandoutContract"
);
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed at:", depAddr);
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function test() {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const transferAmount = hre.ethers.parseEther("0.0001");
var nonce = await hre.ethers.provider.getTransactionCount(signer.address)
nonce = nonce + 1
const signedTx = await signer.signTransaction({
type: 0,
chainId: 10323,
nonce: nonce,
to: "0x88395111AB1586a4030dAC62a183542762929bbC", // first
// to: "0x6ddb3A03366e218956483A840D8BfB490ADE1beB", // second
data: '',
value: transferAmount,
gasLimit: 1000000,
gasPrice: hre.ethers.parseUnits("4", "gwei"),
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent:", txResponse.hash);
}
// Define the script
async function main() {
await test()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function test() {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const transferAmount = hre.ethers.parseEther("0.0001");
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
var nonce = await hre.ethers.provider.getTransactionCount(signer.address)
nonce = nonce - 1
const signedTx = await signer.signTransaction({
type: 0,
chainId: chainId,
nonce: nonce,
to: "0x820b54e2446941213F09d576994B84c32D1ebA2B",
data: '',
value: transferAmount,
gasLimit: 1000000,
gasPrice: hre.ethers.parseUnits("1", "gwei"),
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent:", txResponse.hash);
}
// Define the script
async function main() {
await test()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function testMultiCallMintToken(multicall, token, users) {
// Prepare multicall to mint token for all users.
const iface = new hre.ethers.Interface([
"function mint(address to, uint256 amount)"
]);
let calls = [];
for (let i = 0; i < users.length; i++) {
let user = users[i];
let callData = iface.encodeFunctionData("mint", [user, hre.ethers.parseEther("1000")]);
calls.push({
target: token,
callData: callData
});
}
// Use aggregate3 to mint tokens
let aggregate3Calls = calls.map(call => ({
target: call.target,
allowFailure: false,
callData: call.callData
}));
let results = await multicall.aggregate3(aggregate3Calls);
console.log("test multicall mint token result is ", results);
}
async function testMultiCallGetTokenBalances(multicall, token, users) {
// Prepare multicall to get balances of all users.
const iface = new hre.ethers.Interface([
"function balanceOf(address) view returns (uint256)"
]);
let calls = [];
for (let i = 0; i < users.length; i++) {
let user = users[i];
let callData = iface.encodeFunctionData("balanceOf", [user]);
calls.push({
target: token,
callData: callData
});
// Compute total value (BigInt) to send with the multicall transaction
let totalValue = 0n;
for (let i = 0; i < aggregate3Calls.length; i++) {
totalValue += aggregate3Calls[i].value;
}
// First, simulate the multicall as a read-only call to get the per-call results
try {
const simulated = await multicall.callStatic.aggregate3Value(aggregate3Calls, {value: totalValue});
console.log("Simulated aggregate3Value result:", simulated);
for (let i = 0; i < simulated.length; i++) {
const r = simulated[i];
console.log(`Simulated call ${i} to ${aggregate3Calls[i].target} success: ${r.success}`);
}
} catch (e) {
console.log("Simulation of aggregate3Value failed:", e);
}
// Now send the actual payable transaction
const tx = await multicall.aggregate3Value(aggregate3Calls, {value: totalValue});
const receipt = await tx.wait();
console.log("aggregate3Value transaction mined. txHash:", receipt.transactionHash);
// Use aggregate3 to get balances as a read-only call (no transaction)
let aggregate3Calls = calls.map(call => ({
target: call.target,
allowFailure: false,
callData: call.callData
}));
// Use callStatic to avoid sending a transaction and just simulate the multicall
let results = await multicall.call.aggregate3(aggregate3Calls);
console.log("test multicall get token balances result (raw):", results);
// Decode and print human-readable balances
for (let i = 0; i < results.length; i++) {
const result = results[i];
if (!result.success) {
console.log(`Call failed for ${users[i]}`);
continue;
}
const decoded = iface.decodeFunctionResult("balanceOf", result.returnData);
console.log(`Balance of ${users[i]}: ${hre.ethers.formatEther(decoded[0])} tokens`);
}
}
}
async function testSendEthToUsers(multicall, users) {
// Prepare multicall to send ETH to all users.
let calls = [];
for (let i = 0; i < users.length; i++) {
let user = users[i];
let callData = "0x"; // empty call data for sending ETH
calls.push({
target: user,
callData: callData,
value: hre.ethers.parseEther("0.01") // send 0.01 ETH
});
}
// Use aggregate3 to send ETH
let aggregate3Calls = calls.map(call => ({
target: call.target,
allowFailure: false,
callData: call.callData,
value: call.value
}));
let results = await multicall.aggregate3Value(aggregate3Calls, {value: hre.ethers.parseEther((0.01 * users.length).toString())});
console.log("test multicall send ETH to users result is ", results);
}
async function testMulticallBaseFunction(contract, account) {
var hash = await contract.getBlockHash(128)
console.log("Block hash 128:", hash);
var bn = await contract.getBlockNumber()
console.log("Block number:", bn);
var ts = await contract.getCurrentBlockTimestamp()
console.log("Block timestamp:", ts);
var tc = await contract.getCurrentBlockCoinbase()
console.log("Block coinbase:", tc);
var td = await contract.getCurrentBlockDifficulty()
console.log("Block difficulty:", td);
var tg = await contract.getCurrentBlockGasLimit()
console.log("Block gas limit:", tg);
// var ta = await contract.getBasefee()
// console.log("Block base fee:", ta);
var chainid = await contract.getChainId()
console.log("Chain ID:", chainid);
var balance = await contract.getEthBalance(account)
console.log("Account ETH balance:", hre.ethers.formatEther(balance));
var rpcBalance = await hre.ethers.provider.getBalance(account.address);
console.log("RPC Account ETH balance:", hre.ethers.formatEther(rpcBalance));
var lastRet = await contract.getLastBlockHash()
console.log("Last block hash:", lastRet);
}
// Define the script
async function main() {
async function main() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"Multicall2"
"Multicall3"
);
const accounts = await hre.ethers.getSigners();
const account = accounts[0];
console.log("Deploying contract with account:", accounts[0].address);
// const contract = await factory.deploy({ value: hre.ethers.parseEther("0.0008") });
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed at:", depAddr);
}
// Test base functions
await testMulticallBaseFunction(contract, account);
// Define users
var users = [
"0x0000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000003",
]
// deploy token contract and mint to user list.
var tokenFactory = await hre.ethers.getContractFactory(
"PublicToken"
);
const tokenContract = await tokenFactory.deploy();
await tokenContract.waitForDeployment();
const tokenAddr = await tokenContract.getAddress();
console.log("Token Contract deployed at:", tokenAddr);
// Test minting tokens via multicall
await testMultiCallMintToken(contract, tokenAddr, users);
// check token balance for each user
for (let i = 0; i < users.length; i++) {
let user = users[i];
let balance = await tokenContract.balanceOf(user);
console.log(`Token balance of ${user}: ${hre.ethers.formatEther(balance)} tokens`);
}
// Test getting token balances via multicall
// await testMultiCallGetTokenBalances(contract, tokenAddr, users);
// Test sending ETH to users via multicall
await testSendEthToUsers(contract, users);
// check ETH balance for each user
for (let i = 0; i < users.length; i++) {
let user = users[i];
let balance = await hre.ethers.provider.getBalance(user);
console.log(`ETH balance of ${user}: ${hre.ethers.formatEther(balance)} ETH`);
}
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
......
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
// Define the script
async function main() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"RevertContract"
);
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed at:", depAddr);
// sendViaTransfer
const recipient = "0xa686b69111eaDc74d45eEB3bE4aE487Fd61497E6"; // Replace with the recipient's address
const transferAmount = ethers.parseEther("0.0005"); // 0.0005 ETH
const viaTransfer = await contract.sendViaTransfer(recipient, transferAmount, {value: transferAmount, gas: 1000000, gasPrice: 1000000000});
await viaTransfer.wait();
console.log(`Transferred ${ethers.formatEther(transferAmount)} ETH to ${recipient} via transfer`);
// sendViaCall
const viaCall = await contract.sendViaCall(recipient, transferAmount, {value: transferAmount});
await viaCall.wait();
console.log(`Transferred ${ethers.formatEther(transferAmount)} ETH to ${recipient} via call`);
// sendViaSend
const viaSend = await contract.sendViaSend(recipient, transferAmount, {value: transferAmount});
await viaSend.wait();
console.log(`Transferred ${ethers.formatEther(transferAmount)} ETH to ${recipient} via send`);
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
......@@ -12,7 +12,7 @@ async function test() {
type: 0,
chainId: chainId,
nonce: nonce,
to: "0x88395111AB1586a4030dAC62a183542762929bbC",
to: "0x6ddb3A03366e218956483A840D8BfB490ADE1beB",
data: '',
value: transferAmount,
gasLimit: 1000000,
......@@ -21,7 +21,10 @@ async function test() {
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent:", txResponse.hash);
// wait receipt
await txResponse.wait();
const receipt = await hre.ethers.provider.getTransactionReceipt(txResponse.hash);
console.log("Transaction receipt:", receipt.blockNumber);
}
// Define the script
......
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
var addrlist = [
"0xaccf7aacd00bb765120f10685e58d916d3ec3057",
"0x4631638617F6CF476BeC1AA9A892D308AaE2062A",
"0x43Fa8B58AaBeF30bE4221C7c435Fa38d34f0ccb1",
"0x193b7fBA150679AC96c675964180dA078B73fE3c",
"0x5b89a423416B00769ecB9F148411CD686d165A43",
"0xDF2cf3eE3E4E36490F5f942372fF4c975040bBd0",
"0xdD9720aBe15CD07cc2BF9213C1f08CFf1AE0b37D",
"0xD7FB4128F5451f88A5e525ef5303d714633435A7",
"0xf5c5C8cC784C8183316f4d1f0E50c46DF45920c8",
"0x9923f67774A4250bf2B2eA34Da9cBbc6aBd98caD",
"0xe40701772cCBA7a515CE557c3eaeB4B29B92C71e"
]
async function test() {
const transferAmount = hre.ethers.parseEther("100000");
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
var nonce = await hre.ethers.provider.getTransactionCount(signer.address)
for (let i = 0; i < addrlist.length; i++) {
const signedTx = await signer.signTransaction({
type: 0,
chainId: chainId,
nonce: nonce + i,
to: addrlist[i],
data: '',
value: transferAmount,
gasLimit: 210000,
gasPrice: hre.ethers.parseUnits("1", "gwei"),
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent to:", addrlist[i], " tx hash:", txResponse.hash);
}
console.log("All transactions sent.");
}
// Define the script
async function main() {
await test()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function test() {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const transferAmount = hre.ethers.parseEther("0.0005");
var nonce = await hre.ethers.provider.getTransactionCount(signer.address)
nonce = 27;
const signedTx = await signer.signTransaction({
type: 0,
chainId: 100,
nonce: nonce,
to: "0x88395111AB1586a4030dAC62a183542762929bbC", // first
// to: "0x6ddb3A03366e218956483A840D8BfB490ADE1beB", // second
data: '',
value: transferAmount,
gasLimit: 1000000,
gasPrice: hre.ethers.parseUnits("1", "gwei"),
});
// 发送交易
const txResponse = await hre.ethers.provider.broadcastTransaction(signedTx);
console.log("Transaction sent:", txResponse.hash);
}
// Define the script
async function main() {
await test()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const hre = require("hardhat");
const { ethers } = hre;
// Stress test script: sends contract transactions at a target rate (txs/sec).
// Usage examples:
// DEPLOY_PRIVATE_KEY=... TOKEN_ADDRESS=0x... TPS=20 DURATION_SECONDS=60 node scripts/stress.js
// DEPLOY_PRIVATE_KEY=... DEPLOY_TOKEN=true TPS=50 DURATION_SECONDS=30 node scripts/stress.js
// CONTRACT_TYPE=complex DEPLOY_PRIVATE_KEY=... TPS=20 DURATION_SECONDS=60 node scripts/stress.js
async function main() {
const tps = parseInt(process.env.TPS, 10) || 20; // transactions per second
const durationSeconds = parseInt(process.env.DURATION_SECONDS, 10) || 60; // how long to run
const deployTokenIfMissing = process.env.DEPLOY_TOKEN !== 'false';
let tokenAddr = process.env.TOKEN_ADDRESS || '';
const contractType = (process.env.CONTRACT_TYPE || 'complex').toLowerCase(); // 'simple' or 'complex'
const privateKey = process.env.DEPLOY_PRIVATE_KEY;
// If no private key provided and we're running inside Hardhat (npx hardhat run),
// we can use the provider's unlocked signer (signer[0]) which is pre-funded.
const useProviderSigner = !privateKey;
// Deploy a simple PublicToken if no token address provided
if (!tokenAddr) {
if (!deployTokenIfMissing) {
console.error('No TOKEN_ADDRESS provided and DEPLOY_TOKEN is false. Exiting.');
process.exit(1);
}
if (contractType === 'complex') {
console.log('No TOKEN_ADDRESS provided — deploying a new ComplexToken...');
const tokenFactory = await ethers.getContractFactory('ComplexToken');
const tokenContract = await tokenFactory.deploy('ComplexToken', 'CPLX');
await tokenContract.waitForDeployment();
tokenAddr = await tokenContract.getAddress();
console.log('Deployed ComplexToken at', tokenAddr);
} else {
console.log('No TOKEN_ADDRESS provided — deploying a new PublicToken...');
const tokenFactory = await ethers.getContractFactory('PublicToken');
const tokenContract = await tokenFactory.deploy();
await tokenContract.waitForDeployment();
tokenAddr = await tokenContract.getAddress();
console.log('Deployed PublicToken at', tokenAddr);
}
} else {
console.log('Using token at', tokenAddr);
}
let signer;
let chainId = await ethers.provider.getNetwork().then(n => n.chainId);
let startNonce = undefined;
if (useProviderSigner) {
signer = ethers.provider.getSigner(0);
const addr = await signer.getAddress();
console.log('Using provider signer (no DEPLOY_PRIVATE_KEY). signer=', addr);
// when using provider signer, we will not manually manage nonces; provider handles it
} else {
signer = new ethers.Wallet(privateKey, ethers.provider);
startNonce = await ethers.provider.getTransactionCount(signer.address, 'pending');
console.log('Using wallet signer', signer.address, 'startNonce=', startNonce);
}
// Prepare interface for mint(address,uint256)
let iface;
let mintAmount = ethers.parseEther('1.0');
if (contractType === 'complex') {
const abi = ["function heavyOperation(address[] targets, uint256[] amounts) external"];
iface = new ethers.Interface(abi);
console.log('Configured to call ComplexToken.heavyOperation for each tx');
} else {
const abi = ["function mint(address to, uint256 amount) external"];
iface = new ethers.Interface(abi);
console.log('Configured to call PublicToken.mint for each tx');
}
// Pre-generate a set of recipient addresses to vary targets
const recipients = Array.from({ length: Math.max(100, tps * 5) }, () => ethers.Wallet.createRandom().address);
// Start nonce when using wallet signer; provider signer will auto-manage nonce
let nonce = startNonce;
try {
const signerAddress = useProviderSigner ? await signer.getAddress() : signer.address;
console.log('Starting stress test: TPS=%d, duration=%ds, signer=%s, startNonce=%s', tps, durationSeconds, signerAddress, nonce === undefined ? 'auto' : nonce);
} catch (e) {
console.log('Starting stress test');
}
const stopAt = Date.now() + durationSeconds * 1000;
let totalSent = 0;
const batchIntervalMs = 1000; // send batches every second
// Helper sleep
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
while (Date.now() < stopAt) {
const batchStart = Date.now();
// Target interval between transactions (ms). If TPS is high, this can be 0.
const perTxInterval = Math.floor(1000 / tps);
for (let i = 0; i < tps; i++) {
if (Date.now() >= stopAt) break;
const recipient = recipients[(totalSent + i) % recipients.length];
let data;
if (contractType === 'complex') {
// build arrays for heavyOperation to exercise state changes
const targets = [recipient, recipients[(totalSent + i + 1) % recipients.length], recipients[(totalSent + i + 2) % recipients.length]];
const amounts = [ethers.parseEther('0.1'), ethers.parseEther('0.05'), ethers.parseEther('0.02')];
data = iface.encodeFunctionData('heavyOperation', [targets, amounts]);
} else {
data = iface.encodeFunctionData('mint', [recipient, mintAmount]);
}
const baseTx = {
to: tokenAddr,
data: data,
value: 0,
gasLimit: 500000,
gasPrice: ethers.parseUnits('1', 'gwei'),
};
let tx = Object.assign({}, baseTx);
if (!useProviderSigner) {
tx = Object.assign(tx, { nonce: nonce++, chainId: chainId, type: 0 });
}
const sendStart = Date.now();
try {
if (useProviderSigner) {
const res = await signer.sendTransaction(tx);
console.log('sent tx', res.hash);
} else {
const signed = await signer.signTransaction(tx);
const res = await ethers.provider.broadcastTransaction(signed);
console.log('broadcasted', res.hash, 'nonce', tx.nonce);
}
} catch (err) {
console.error('tx send/broadcast error (nonce=' + (tx.nonce ? tx.nonce : 'n/a') + '):', err && err.message ? err.message : err);
}
totalSent += 1;
// pace to target TPS
const elapsedTx = Date.now() - sendStart;
const waitFor = Math.max(0, perTxInterval - elapsedTx);
if (waitFor > 0) await sleep(waitFor);
}
// Sleep until the next second boundary if we finished early
const elapsed = Date.now() - batchStart;
const waitNext = Math.max(0, batchIntervalMs - elapsed);
if (waitNext > 0) await sleep(waitNext);
}
console.log('Stress test finished. Total txs attempted:', totalSent);
}
main().catch(err => {
console.error('Fatal error in stress script:', err);
process.exit(1);
});
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function getTokenInfo(contract) {
const name = await contract.name();
console.log("Token Name:", name);
const symbol = await contract.symbol();
const totalSupply = await contract.totalSupply();
console.log("Token Symbol:", symbol);
console.log("Total Supply:", totalSupply.toString());
}
// Define the script
async function main() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"TestToken"
);
{
const contract = await factory.deploy("TestTokenAlice", "TTA");
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("TTA deployed at:", depAddr);
await getTokenInfo(contract);
}
{
const contract = await factory.deploy("TestTokenBob", "TTB");
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("TTB deployed at:", depAddr);
await getTokenInfo(contract);
}
{
const contract = await factory.deploy("TestTokenCharlie", "TTC");
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("TTC deployed at:", depAddr);
await getTokenInfo(contract);
}
{
const contract = await factory.deploy("TestTokenDoody", "TTD");
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("TTD deployed at:", depAddr);
await getTokenInfo(contract);
}
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
const {ethers} = require("hardhat");
async function deploy() {
[owner] = await ethers.getSigners();
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"TestAbi"
);
const contract = await factory.deploy(owner.address);
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed for mova at:", depAddr);
const params = {
toChainID: 2,
receiver: "0x000000000000000000000000000000000000dead",
token: "0x000000000000000000000000000000000000beef",
amount: hre.ethers.parseEther("10"),
outId: 1,
fromChainID: 1,
sender: "0x000000000000000000000000000000000000cafe",
sendToken: "0x000000000000000000000000000000000000babe",
sendAmount: hre.ethers.parseEther("10"),
signature: "0x000000000000000000000000000000000000babe000000000000000000000000",
};
const tx = await contract.getSubmitData(params);
console.log("Computed hash:", tx);
}
async function initForMovaChain(bridge) {
await addValidators(bridge, initialValidators);
}
// Define the script
async function main() {
await deploy();
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function test() {
const signer = new hre.ethers.Wallet(process.env.DEPLOY_PRIVATE_KEY, hre.ethers.provider);
const chainId = await hre.ethers.provider.getNetwork().then(network => network.chainId);
const TestMCOPY = await ethers.getContractFactory("TestMCOPY");
testMCOPY = await TestMCOPY.deploy();
await testMCOPY.waitForDeployment();
console.log("Deployed TestMCOPY at address:", testMCOPY.target);
console.log("Calling TestMCOPY.testExplicitMCopy()");
const result = await testMCOPY.testExplicitMCopy();
console.log("Result:", result);
const TTest = await ethers.getContractFactory("TTest");
ttest = await TTest.deploy();
await ttest.waitForDeployment();
console.log("Deployed TTest at address:", ttest.target);
try {
console.log("Calling TTest.testBASEFEE()");
const basefee = await ttest.testBASEFEE();
console.log("Result:", basefee.toString());
} catch (error) {
console.error("Error calling testBASEFEE:", error.message);
}
try {
console.log("Calling TTest.testPREVRANDAO()");
const prevrandao = await ttest.testPREVRANDAO();
console.log("Result:", prevrandao.toString());
} catch (error) {
console.error("Error calling testPREVRANDAO:", error.message);
}
try {
console.log("Calling TTest.testBLOBHASH()");
const blobhash = await ttest.testBLOBHASH();
console.log("Result:", blobhash);
} catch (error) {
console.error("Error calling testBLOBHASH:", error.message);
}
try {
console.log("Calling TTest.testBLOBFEE()");
const blobfee = await ttest.testBLOBFEE();
console.log("Result:", blobfee.toString());
} catch (error) {
console.error("Error calling test:", error.message);
}
try {
console.log("Calling TTest.test()");
const tx = await ttest.test();
await tx.wait();
console.log("TTest.test() called successfully");
} catch (error) {
console.error("Error calling test:", error.message);
}
}
// Define the script
async function main() {
await test()
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
async function getTokenInfo(contract) {
const name = await contract.name();
console.log("Token Name:", name);
const symbol = await contract.symbol();
const totalSupply = await contract.totalSupply();
console.log("Token Symbol:", symbol);
console.log("Total Supply:", totalSupply.toString());
}
// Define the script
async function main() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"PublicToken"
);
// const contract = await factory.deploy({ value: hre.ethers.parseEther("0.0008") });
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed at:", depAddr);
await getTokenInfo(contract);
// const minttx = await contract.mint('0x88395111AB1586a4030dAC62a183542762929bbC', 10000);
// console.log("mint tx:", minttx.hash);
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
// Define the script
async function main() {
// Deploy the contract
const factory = await hre.ethers.getContractFactory(
"WMDD"
);
const contract = await factory.deploy();
await contract.waitForDeployment();
const depAddr = await contract.getAddress();
console.log("Contract deployed at:", depAddr);
}
// Run the script
main().catch((error) => {
console.error("Error:", error);
});
\ No newline at end of file
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