Skip to content

Instantly share code, notes, and snippets.

@SKYBITDev3
Created October 8, 2023 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SKYBITDev3/57a385d1c7a067de22ab6e6a598bca7e to your computer and use it in GitHub Desktop.
Save SKYBITDev3/57a385d1c7a067de22ab6e6a598bca7e to your computer and use it in GitHub Desktop.
async function main() {
const { ethers, network } = require(`hardhat`)
const [ wallet1, wallet2 ] = await ethers.getSigners()
// const walletToUse = wallet1 // switch between wallet1 & wallet2 to see the difference in addresses
const walletToUse = wallet2 // switch between wallet1 & wallet2 to see the difference in addresses
console.log(`Using network: ${network.name} (${network.config.chainId}), account: ${walletToUse.address} having ${await ethers.formatUnits(await ethers.provider.getBalance(walletToUse.address), `ether`)} of native currency, RPC url: ${network.config.url}`)
// Deploy factory
const addressOfFactory = `0xaf45f86eb0bbf0536fa770b699b806f22496d875` // If evmVersion = shanghai. See https://github.com/SKYBITDev3/deterministic-deployment-proxy. Difference with Arachnid's factory is that here user's address is hashed with salt
if (await ethers.provider.getCode(addressOfFactory) === `0x`) {
// Fund account of signer of transaction that deploys factory.
const addressOfSignerToDeployFactory = `0x790bec4474aff8686ab85225584988f9622efff5` // If evmVersion = shanghai
let txResponse = await walletToUse.sendTransaction({ to: addressOfSignerToDeployFactory, value: ethers.parseUnits(`0.1`, `ether`) })
await txResponse.wait()
const txSserialized = `0xf8858085174876e800830186a08080b4602a80600a5f395ff3fe5f33815280356020526034600c20601f19360180602084378234f5908115602757526014600cf35b80fd1ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222` // If evmVersion = shanghai
txResponse = await ethers.provider.broadcastTransaction(txSserialized)
const txReceipt = await txResponse.wait()
// console.log(`txReceipt: ${JSON.stringify(txReceipt)}`)
}
console.log(`Address of factory deployed keylessly: ${addressOfFactory}`)
// Deploy Contract via factory
// get contract bytecode
const contractName = `TESTERC20`
const constructorArgs = [
`Token 4630`,
`TOKEN4630`,
100,
[ wallet1.address, wallet2.address ], // test array constructor argument
{ x: 10, y: 5 }, // test struct constructor argument
`0xabcdef`, // test byte constructor argument. bytes have to be 0x-prefixed
]
const cfToken = await ethers.getContractFactory(contractName)
const bytecodeOfContractWithArgs = (await cfToken.getDeployTransaction(...constructorArgs)).data
// const salt = ethers.encodeBytes32String(``) // 0x0000000000000000000000000000000000000000000000000000000000000000
const salt = ethers.encodeBytes32String(`XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`)
const txData = {
from: walletToUse.address,
to: addressOfFactory,
data: bytecodeOfContractWithArgs.replace(`0x`, salt),
}
const expectedAddressUsingCall = await walletToUse.call(txData)
console.log(`expected address using await walletToUse.call(txData): ${expectedAddressUsingCall}`)
const keccak256Calculated = ethers.solidityPackedKeccak256([ `address`, `bytes32` ], [ walletToUse.address, salt ])
const expectedAddressCalculated = ethers.getCreate2Address(addressOfFactory, keccak256Calculated, ethers.keccak256(bytecodeOfContractWithArgs))
console.log(`expected address using ethers.getCreate2Address: ${expectedAddressCalculated}`)
console.log(`Now deploying ${contractName} using factory...`)
const txReceipt = await walletToUse.sendTransaction(txData)
await txReceipt.wait()
console.log(`${contractName} was deployed by ${walletToUse.address}`)
console.log(`Testing deployed contract by getting contract at address ${expectedAddressUsingCall}:`)
const contract = await ethers.getContractAt(contractName, expectedAddressUsingCall, walletToUse)
console.log(`${walletToUse.address} calling contract.point(): ${await contract.point()}`) // Test deployed Contract contract at expected address
console.log(`${walletToUse.address} calling contract.privilegedFunction(): ${await contract.privilegedFunction()}`) // Test function that only a privileged account can call
}
main().catch(error => {
console.error(error)
process.exitCode = 1
})
Using network: hardhat (31337), account: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 having 10000.0 of native currency, RPC url: undefined
Address of factory deployed keylessly: 0xaf45f86eb0bbf0536fa770b699b806f22496d875
expected address using await walletToUse.call(txData): 0xe32dcd55a5daee6e5a34b046f759721c76e78291
expected address using ethers.getCreate2Address: 0xE32dcD55a5daEE6E5A34b046F759721C76E78291
Now deploying TESTERC20 using factory...
TESTERC20 was deployed by 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Testing deployed contract by getting contract at address 0xe32dcd55a5daee6e5a34b046f759721c76e78291:
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 calling contract.point(): 10,5
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 calling contract.privilegedFunction(): 1
Using network: hardhat (31337), account: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 having 10000.0 of native currency, RPC url: undefined
Address of factory deployed keylessly: 0xaf45f86eb0bbf0536fa770b699b806f22496d875
expected address using await walletToUse.call(txData): 0xbb1070bb427b517cb6ecfc2b1ef08ec413259277
expected address using ethers.getCreate2Address: 0xbb1070bb427B517Cb6Ecfc2B1ef08ec413259277
Now deploying TESTERC20 using factory...
TESTERC20 was deployed by 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
Testing deployed contract by getting contract at address 0xbb1070bb427b517cb6ecfc2b1ef08ec413259277:
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 calling contract.point(): 10,5
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 calling contract.privilegedFunction(): 1
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
// import "hardhat/console.sol";
struct Point {
uint x;
uint y;
}
contract TESTERC20 is ERC20, ERC20Permit, AccessControl {
Point public point;
bytes public b;
constructor(
string memory name,
string memory symbol,
uint initialSupply,
address[] memory initialHolders,
Point memory _point,
bytes memory _b
) ERC20(name, symbol) ERC20Permit(name) {
_mint(
initialHolders[0],
(10 * (initialSupply * 10 ** decimals())) / 100
);
_mint(
initialHolders[1],
(90 * (initialSupply * 10 ** decimals())) / 100
);
point = _point;
b = _b;
// _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); // if deploying this contract via a factory then msg.sender is factory's address
_grantRole(
DEFAULT_ADMIN_ROLE,
tx.origin
);
}
function privilegedFunction()
public
view
onlyRole(DEFAULT_ADMIN_ROLE)
returns (uint8)
{
return 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment