Skip to content

Commit

Permalink
Updated SKYBITCREATE3FactoryLite code & addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
- committed Sep 14, 2023
1 parent 693248a commit c4d29d3
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 61 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ Gas used for the deployment is 84,540 (or a little more for some blockchains), s

The SKYBITLite factory contract will be deployed to this address (if the transaction bytecode is unchanged):
```
0xe3dCDc516f75Fcd8CA7f3Ecb8387fb85CF0AbEDd
0xcAb20EC9d599aCc6253be7fbfB1fa215E8c9f993
```
The derived address of the account that would sign the deployment transaction, and that you'd need to fund in order to pay the gas fee, is:
```
0x62dF0289c0120c00A7a67a353cD2600A882d8198
0xb40a5c3217929e1b2631debb680b7C50ec054EBc
```


Expand Down Expand Up @@ -225,11 +225,11 @@ In `hardhat.config.js` do the following:

Set `accounts` to the one(s) that you will use.

Check whether the blockchains you will use are listed in [@wagmi/chains](https://github.com/wagmi-dev/references/blob/main/packages/chains/src/index.ts). If not, then add the blockchain info in `additionalNetworks`.
Check whether the blockchains you will use are listed in [@wagmi/chains](https://github.com/wagmi-dev/viem/blob/main/src/chains/index.ts). If not, then add the blockchain info in `additionalNetworks`.

For the few blockchain names in [@wagmi/chains](https://github.com/wagmi-dev/references/blob/main/packages/chains/src/index.ts) that don't match exactly with names in [hardhat-verify](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-verify/src/internal/chain-config.ts), use the [hardhat-verify](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-verify/src/internal/chain-config.ts) version as shown in this table:
For the few blockchain names in [@wagmi/chains](https://github.com/wagmi-dev/viem/blob/main/src/chains/index.ts) that don't match exactly with names in [hardhat-verify](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-verify/src/internal/chain-config.ts), use the [hardhat-verify](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-verify/src/internal/chain-config.ts) version as shown in this table:

| In [@wagmi/chains](https://github.com/wagmi-dev/references/blob/main/packages/chains/src/index.ts) | In [hardhat-verify](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-verify/src/internal/chain-config.ts) (use these) |
| In [@wagmi/chains](https://github.com/wagmi-dev/viem/blob/main/src/chains/index.ts) | In [hardhat-verify](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-verify/src/internal/chain-config.ts) (use these) |
|--|--|
| arbitrum | arbitrumOne |
| avalancheFuji | avalancheFujiTestnet |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"contractName": "SKYBITCREATE3FactoryLite",
"sourceName": "contracts/SKYBITCREATE3FactoryLite.yul",
"abi": [],
"bytecode": "0x60918061000b5f395ff3fe34608d575f6f67363d3d37363d34f03d5260086018f38152336020528035604052604060202060108083f59081156080578160145261d6948152600160345380806017601e20938180601f1936019283602083375af115607357813b15606657526014600cf35b63326bd13990526004601cfd5b63ec4cb4b690526004601cfd5b63335e7dd590526004601cfd5b5f80fd",
"bytecode": "0x60898061000b5f395ff3fe34606b575f601980607083393360205281356040526040602020908280f58015605e57816014918180601f1936019283602083375af115605157805115604457601490f35b63326bd13990526004601cfd5b63ec4cb4b690526004601cfd5b636e0df51b82526004601cfd5b5f80fdfe600f80600a5f395ff3fe365f8037365f80f05f526014600cf3",
"linkReferences": {},
"deployedLinkReferences": {}
}
81 changes: 30 additions & 51 deletions contracts/SKYBITCREATE3FactoryLite.yul
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT

/// @notice A factory contract that deploys a contract from bytecode using "CREATE3" method. Derived from https://github.com/Vectorized/solady/blob/main/src/utils/CREATE3.sol
/// @notice A factory contract that deploys a contract from bytecode using "CREATE3" method.
/// @author SKYBIT (https://github.com/SKYBITDev3/SKYBIT-Keyless-Deployment)
object "SKYBITCREATE3FactoryLite" {
code { // Constructor code of the contract
Expand All @@ -12,76 +12,55 @@ object "SKYBITCREATE3FactoryLite" {
code { // Executable code of the object
if gt(callvalue(), 0) { revert(0, 0) } // Protection against sending Ether

/**
@notice The bytecode for a contract that proxies the creation of another contract
@dev If this code is deployed using CREATE2 it can be used to decouple `creationCode` from the child contract address
0x67363d3d37363d34f03d5260086018f3:
0x00 0x67 0x67XXXXXXXXXXXXXXXX PUSH8 bytecode 0x363d3d37363d34f0
0x01 0x3d 0x3d RETURNDATASIZE 0 0x363d3d37363d34f0
0x02 0x52 0x52 MSTORE
0x03 0x60 0x6008 PUSH1 08 8
0x04 0x60 0x6018 PUSH1 18 24 8
0x05 0xf3 0xf3 RETURN
0x363d3d37363d34f0:
0x00 0x36 0x36 CALLDATASIZE cds
0x01 0x3d 0x3d RETURNDATASIZE 0 cds
0x02 0x3d 0x3d RETURNDATASIZE 0 0 cds
0x03 0x37 0x37 CALLDATACOPY
0x04 0x36 0x36 CALLDATASIZE cds
0x05 0x3d 0x3d RETURNDATASIZE 0 cds
0x06 0x34 0x34 CALLVALUE val 0 cds
0x07 0xf0 0xf0 CREATE addr
*/
mstore(0, 0x67363d3d37363d34f03d5260086018f3) // Store the CREATE proxy bytecode (16 bytes) into scratch space.

datacopy(0, dataoffset("CREATEFactory"), datasize("CREATEFactory")) // Write CREATEFactory bytecode to memory position 0. 25 bytes on left of slot, 0-padded on right
mstore(0x20, caller()) // 32 bytes. to be hashed with salt to help ensure unique address.
mstore(0x40, calldataload(0)) // User-provided salt (32 bytes)

let proxy:= create2(0, 0x10, 0x10, keccak256(0x20, 0x40)) // Deploy the CREATE proxy via CREATE2, store address on the stack
let createFactoryAddress := create2(0, 0, datasize("CREATEFactory"), keccak256(0x20, 0x40)) // Deploy the CREATE factory via CREATE2, store address on the stack

if iszero(proxy) {
mstore(0, 0x335e7dd5) // Store ABI encoding of `Deployment of CREATE proxy failed`
if iszero(createFactoryAddress) {
mstore(0, 0x6e0df51b) // Store ABI encoding of `Deployment of CREATEFactory contract failed`
revert(0x1c, 4) // Revert with the stored 4 bytes skipping 0-padding
}

mstore(0x14, proxy) // Store the proxy's address. The actual address starts at 0x20 because of 0-padding on left. Positioned so that RLP encoding prefix can be placed just before.

// "if a string is 0-55 bytes long, the RLP encoding consists of a single byte with value 0x80 (dec. 128) plus the length of the string followed by the string."
// "If the total payload of a list (i.e. the combined length of all its items being RLP encoded) is 0-55 bytes long, the RLP encoding consists of a single byte with value 0xc0 plus the length of the list followed by the concatenation of the RLP encodings of the items"
// Source: https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp
// 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01)
// 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
mstore(0, 0xd694) // Store RLP encoding prefix just before proxy address
mstore8(0x34, 1) // Store single byte: nonce of the proxy contract just after proxy address. EIP-161 specifies contract nonce to start at 1.

let deployed:= keccak256(0x1e, 0x17) // Address from CREATE = hash of RLP-encoded proxy address and nonce

calldatacopy(0, 32, sub(calldatasize(), 32)) // Overwrite scratch at memory position 0 with incoming creationCode. We take full control of memory because it won't return to Solidity code. We don't need the previously stored data anymore.
calldatacopy(0, 32, sub(calldatasize(), 32)) // Overwrite scratch at memory position 0 with incoming creation code (skipping first 32 bytes which is salt), saving gas. We take full control of memory because it won't return to Solidity code. We don't need the previously stored data anymore.

if iszero(
call( // Use the CREATE proxy to deploy the users' contract. Returns 1 if successful.
call( // Use the deployed CREATEFactory to deploy the users' contract. Returns 0 on error (eg. out of gas) and 1 on success.
gas(), // Gas remaining
proxy, // Proxy's address
createFactoryAddress,
0, // Ether value
0, // Start of `creationCode`
sub(calldatasize(), 32), // Length of `creationCode`
0, // Offset of output
0 // Length of output
0, // Start of contract bytecode or "creation code"
sub(calldatasize(), 32), // Length of contract bytecode
0, // Offset of output (resulting address of deployed user's contract)
20 // Length of output
)
) {
mstore(0, 0xec4cb4b6) // Store ABI encoding of `CREATE proxy call failed`
mstore(0, 0xec4cb4b6) // Store ABI encoding of `CREATEFactory call failed`
revert(0x1c, 4)
}

if iszero(extcodesize(deployed)) {
if iszero(mload(0)) {
mstore(0, 0x326bd139) // Store ABI encoding of `Contract nonexistent at expected address`
revert(0x1c, 4)
}

mstore(0, deployed)
return (12, 20) // Addresses are only 20 bytes, so skip the first 12 bytes as it's just 0-padding
return (0, 20) // Return the call output, which is the address of the contract that was deployed via CREATEFactory
}

object "CREATEFactory" {
code {
datacopy(0, dataoffset("runtime"), datasize("runtime"))
return (0, datasize("runtime"))
}

object "runtime" {
code {
calldatacopy(0, 0, calldatasize())
mstore(0, create(0, 0, calldatasize()))
return (12, 20) // Addresses are only 20 bytes, so skip the first 12 bytes
}
}
}
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "SKYBIT-Keyless-Deployment",
"version": "2.8.2",
"version": "2.9.0",
"packageManager": "yarn@3.6.1",
"devDependencies": {
"@Vectorized/solady": "https://github.com/Vectorized/solady#03f3fd05fb1da76edc4df83ae6bf32a842c15f12",
Expand Down
2 changes: 1 addition & 1 deletion scripts/deployKeylessly-Create3Factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const getGasLimit = (factory) => {
break
case `SKYBITLite`:
default:
return 100000n // Gas cost: 84540
return 100000n // Gas cost: 82812
}
}

Expand Down
2 changes: 1 addition & 1 deletion scripts/deployViaCREATE3-TESTERC20.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { ethers, network } = require(`hardhat`)
// const addressOfFactory = `0x619Bdd2F58Ba735e9390D7B177e5Ca3C410bf98c` // gas cost: 2140281

const factoryToUse = `SKYBITLite`
const addressOfFactory = `0xe3dCDc516f75Fcd8CA7f3Ecb8387fb85CF0AbEDd` // gas cost: 2115714
const addressOfFactory = `0xcAb20EC9d599aCc6253be7fbfB1fa215E8c9f993` // gas cost: 2075520


// PASS YOUR OWN STRING HERE TO GENERATE A UNIQUE SALT. After doing your first production deployment, don't change it in order to have same address on other blockchains.
Expand Down
2 changes: 1 addition & 1 deletion scripts/deployViaCREATE3-TESTERC20UG.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const { ethers, network, upgrades } = require(`hardhat`)
// const addressOfFactory = `0x619Bdd2F58Ba735e9390D7B177e5Ca3C410bf98c`

const factoryToUse = `SKYBITLite`
const addressOfFactory = `0xe3dCDc516f75Fcd8CA7f3Ecb8387fb85CF0AbEDd`
const addressOfFactory = `0xcAb20EC9d599aCc6253be7fbfB1fa215E8c9f993`

const isDeployEnabled = true // toggle in case you do deployment and verification separately.

Expand Down

0 comments on commit c4d29d3

Please sign in to comment.