Skip to content

Commit

Permalink
adding zksync wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
yashnevatia committed Jan 15, 2025
1 parent 6ac05d7 commit 2632051
Show file tree
Hide file tree
Showing 21 changed files with 5,497 additions and 144 deletions.
106 changes: 59 additions & 47 deletions contracts/scripts/native_solc_compile_all_ccip
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ echo " │ Compiling CCIP contracts... │"
echo " └──────────────────────────────────────────────┘"

SOLC_VERSION="0.8.24"
ZKSOLC_VERSION="1.5.3"
OPTIMIZE_RUNS=26000
OPTIMIZE_RUNS_OFFRAMP=18000
OPTIMIZE_RUNS_ONRAMP=4100
Expand Down Expand Up @@ -52,56 +53,67 @@ compileContract () {
--bin-runtime --hashes --metadata --metadata-literal --combined-json abi,hashes,metadata,srcmap,srcmap-runtime \
--evm-version paris \
"$ROOT"/contracts/src/v0.8/"$1"

zksolc --overwrite -O3 --metadata-hash none \
-o "$ROOT"/contracts/zksolc/v$ZKSOLC_VERSION/"$contract" \
--bin --allow-paths "$ROOT"/contracts/src/v0.8 \
--metadata-literal \
--evm-version paris \
"$ROOT"/contracts/src/v0.8/"$1"
}


# Solc produces and overwrites intermediary contracts.
# Contracts should be ordered in reverse-import-complexity-order to minimize overwrite risks.
compileContract ccip/offRamp/EVM2EVMOffRamp.sol
compileContract ccip/offRamp/OffRamp.sol
compileContract ccip/applications/PingPongDemo.sol
compileContract ccip/applications/SelfFundedPingPong.sol
compileContract ccip/applications/EtherSenderReceiver.sol
compileContract ccip/onRamp/OnRamp.sol
# compileContract ccip/offRamp/EVM2EVMOffRamp.sol
compileContract ccip/onRamp/EVM2EVMOnRamp.sol
compileContract ccip/CommitStore.sol
compileContract ccip/MultiAggregateRateLimiter.sol
compileContract ccip/Router.sol
compileContract ccip/PriceRegistry.sol
compileContract ccip/RMN.sol
compileContract ccip/ARMProxy.sol
compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol
compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol
compileContract ccip/capability/CCIPConfig.sol
compileContract ccip/capability/interfaces/IOCR3ConfigEncoder.sol
compileContract ccip/NonceManager.sol
compileContract shared/token/ERC677/BurnMintERC677.sol


# Pools
compileContract ccip/pools/LockReleaseTokenPool.sol
compileContract ccip/pools/BurnMintTokenPool.sol
compileContract ccip/pools/BurnFromMintTokenPool.sol
compileContract ccip/pools/BurnWithFromMintTokenPool.sol
compileContract ccip/pools/LockReleaseTokenPoolAndProxy.sol
compileContract ccip/pools/BurnMintTokenPoolAndProxy.sol
compileContract ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol
compileContract ccip/pools/TokenPool.sol


# Test helpers
compileContract ccip/test/helpers/BurnMintERC677Helper.sol
compileContract ccip/test/helpers/CommitStoreHelper.sol
compileContract ccip/test/helpers/MessageHasher.sol
compileContract ccip/test/helpers/CCIPReaderTester.sol
compileContract ccip/test/helpers/ReportCodec.sol
compileContract ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol
compileContract ccip/test/helpers/MultiOCR3Helper.sol
compileContract ccip/test/mocks/MockE2EUSDCTokenMessenger.sol
compileContract ccip/test/mocks/MockE2EUSDCTransmitter.sol
compileContract ccip/test/WETH9.sol

# Customer contracts
compileContract ccip/pools/USDC/USDCTokenPool.sol

compileContract tests/MockV3Aggregator.sol
# compileContract ccip/applications/PingPongDemo.sol
# compileContract ccip/applications/SelfFundedPingPong.sol
# compileContract ccip/CommitStore.sol
# compileContract ccip/Router.sol
# compileContract ccip/PriceRegistry.sol
# compileContract ccip/RMN.sol
# compileContract ccip/ARMProxy.sol
# compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol
# compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol
# compileContract ccip/pools/LockReleaseTokenPool.sol
# compileContract ccip/test/WETH9.sol
# compileContract shared/token/ERC677/LinkToken.sol


# compileContract ccip/offRamp/OffRamp.sol
# compileContract ccip/applications/EtherSenderReceiver.sol
# compileContract ccip/onRamp/OnRamp.sol
# compileContract ccip/MultiAggregateRateLimiter.sol
# compileContract ccip/capability/CCIPConfig.sol
# compileContract ccip/capability/interfaces/IOCR3ConfigEncoder.sol
# compileContract ccip/NonceManager.sol
# compileContract shared/token/ERC677/BurnMintERC677.sol


# # Pools
# compileContract ccip/pools/BurnMintTokenPool.sol
# compileContract ccip/pools/BurnFromMintTokenPool.sol
# compileContract ccip/pools/BurnWithFromMintTokenPool.sol
# compileContract ccip/pools/LockReleaseTokenPoolAndProxy.sol
# compileContract ccip/pools/BurnMintTokenPoolAndProxy.sol
# compileContract ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol
# compileContract ccip/pools/TokenPool.sol


# # Test helpers
# compileContract ccip/test/helpers/BurnMintERC677Helper.sol
# compileContract ccip/test/helpers/CommitStoreHelper.sol
# compileContract ccip/test/helpers/MessageHasher.sol
# compileContract ccip/test/helpers/CCIPReaderTester.sol
# compileContract ccip/test/helpers/ReportCodec.sol
# compileContract ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol
# compileContract ccip/test/helpers/MultiOCR3Helper.sol
# compileContract ccip/test/mocks/MockE2EUSDCTokenMessenger.sol
# compileContract ccip/test/mocks/MockE2EUSDCTransmitter.sol


# # Customer contracts
# compileContract ccip/pools/USDC/USDCTokenPool.sol

# compileContract tests/MockV3Aggregator.sol
6 changes: 4 additions & 2 deletions contracts/src/v0.8/ccip/test/WETH9.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ contract WETH9 {
_deposit();
}

function withdraw(uint256 wad) external {
function withdraw(uint256 wad) public {
require(balanceOf[msg.sender] >= wad);
balanceOf[msg.sender] -= wad;
payable(msg.sender).transfer(wad);
// Replace transfer with call
(bool success,) = payable(msg.sender).call{value: wad}("");
require(success, "WETH9: ETH transfer failed");
emit Withdrawal(msg.sender, wad);
}

Expand Down
197 changes: 196 additions & 1 deletion core/gethwrappers/abigen.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const headerComment = `// Code generated - DO NOT EDIT.
// AbigenArgs is the arguments to the abigen executable. E.g., Bin is the -bin
// arg.
type AbigenArgs struct {
Bin, ABI, Out, Type, Pkg string
Bin, ABI, Out, Type, Pkg, ZkBinPath string
}

// Abigen calls Abigen with the given arguments
Expand Down Expand Up @@ -72,6 +72,9 @@ func Abigen(a AbigenArgs) {
}

ImproveAbigenOutput(a.Out, a.ABI)
if a.ZkBinPath != "" {
ImproveAbigenOutputZks(a.Out, a.ZkBinPath)
}
}

func ImproveAbigenOutput(path string, abiPath string) {
Expand Down Expand Up @@ -466,3 +469,195 @@ func writeInterface(contractName string, fileNode *ast.File) *ast.File {
func addHeader(code []byte) []byte {
return utils.ConcatBytes([]byte(headerComment), code)
}

// ZK stack logic
func ImproveAbigenOutputZks(path string, zkBinPath string) {
bs, err := os.ReadFile(path)
if err != nil {
Exit("Error while improving abigen output", err)
}

fset, fileNode := parseFile(bs)

contractName := getContractName(fileNode)

zkByteCode, err := os.ReadFile(zkBinPath)
if err != nil {
Exit("Error while improving abigen output", err)
}
zkHexString := string(zkByteCode)

// add zksync binary to the wrapper
fileNode = addZKSyncBin(fileNode, contractName, zkHexString)

// add zksync logic to the deploy function
fileNode = updateDeployMethod(contractName, fset, fileNode)

bs = generateCode(fset, fileNode)

err = os.WriteFile(path, bs, 0600)
if err != nil {
Exit("Error while writing improved abigen source", err)
}
}

// add zksync binary to the wrapper
func addZKSyncBin(fileNode *ast.File, contractName string, zkHexString string) *ast.File {
// zksync
newVarSpec := &ast.ValueSpec{
Names: []*ast.Ident{ast.NewIdent(contractName + "ZKBin")},
Values: []ast.Expr{
&ast.BasicLit{
Kind: token.STRING,
Value: fmt.Sprintf("(\"%s\")", zkHexString),
},
},
}
newVarDecl := &ast.GenDecl{
Tok: token.VAR,
Specs: []ast.Spec{newVarSpec},
}

// Insert the new variable declaration at the top of the file (before existing functions)
fileNode.Decls = append(fileNode.Decls, newVarDecl)
return fileNode
}

// add zksync logic to the deploy function
func updateDeployMethod(contractName string, fset *token.FileSet, fileNode *ast.File) *ast.File {

return astutil.Apply(fileNode, func(cursor *astutil.Cursor) bool {
x, is := cursor.Node().(*ast.FuncDecl)
if !is {
return true
} else if x.Name.Name != "Deploy"+contractName {
return false
}

// only add this import if Deploy method found
astutil.AddImport(fset, fileNode, "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated")

// Extract the parameters from the existing function x
paramList := getConstructorParams(x.Type.Params.List)
// get the `if zksync()` block
zkSyncBlock := getZKSyncBlock(contractName, paramList)
// insert the `if zksync()` block
addZKSyncBlock(*x, zkSyncBlock)
// update the return type in the function signature
updateTxReturnType(*x)
// update the actual return value
updateReturnStmt(*x)

return false
}, nil).(*ast.File)
}

// get the `if zksync()` block
func getZKSyncBlock(contractName, paramList string) string {
zkSyncBlock := `if generated.IsZKSync(backend) {
address, ethTx, contractBind, _ := generated.DeployContract(auth, parsed, common.FromHex(%sZKBin), backend, %params)
contractReturn := &%s{address: address, abi: *parsed, %sCaller: %sCaller{contract: contractBind}, %sTransactor: %sTransactor{contract: contractBind},%sFilterer: %sFilterer{contract: contractBind}}
return address, ethTx, contractReturn, err
}`
zkSyncBlock = strings.ReplaceAll(zkSyncBlock, "%s", contractName)
zkSyncBlock = strings.ReplaceAll(zkSyncBlock, "%params", paramList)
return strings.ReplaceAll(zkSyncBlock, "%s", contractName)
}

// Extract the parameters for constructor function
func getConstructorParams(contstructorParams []*ast.Field) string {
params := []string{}
for i, param := range contstructorParams {
if i > 1 { // Skip auth and backend
for _, name := range param.Names {
params = append(params, name.Name)
}
}
}
paramList := strings.Join(params, ", ")
return paramList
}

// insert the `if zksync()` block
func addZKSyncBlock(x ast.FuncDecl, zkSyncBlock string) ast.FuncDecl {
for i, stmt := range x.Body.List {

ifStmt, ok := stmt.(*ast.IfStmt)
if !ok {
continue
}
binaryExpr, ok := ifStmt.Cond.(*ast.BinaryExpr)
if !ok {
continue
}
if ident, ok := binaryExpr.X.(*ast.Ident); ok && ident.Name == "parsed" {
// Creating new statement to insert
newStmt := &ast.ExprStmt{
X: &ast.BasicLit{
Kind: token.STRING,
Value: zkSyncBlock,
},
}

// Insert the new statement after the current statement
x.Body.List = append(x.Body.List[:i+1], append([]ast.Stmt{newStmt}, x.Body.List[i+1:]...)...)
break
}
}
return x
}

// convert *types.Transaction to *generated_zks.Transaction
func updateTxReturnType(x ast.FuncDecl) {
x.Type.Results.List[1].Type = &ast.StarExpr{
X: &ast.SelectorExpr{
X: &ast.Ident{Name: "generated"},
Sel: &ast.Ident{Name: "Transaction"},
},
}
}

// convert tx to &Transaction{Transaction: tx, HashZks: tx.Hash()}
func updateReturnStmt(x ast.FuncDecl) {
for _, stmt := range x.Body.List {
returnStmt, is := stmt.(*ast.ReturnStmt)
if !is {
continue
}
if len(returnStmt.Results) < 3 {
continue
}

txExpr, ok := returnStmt.Results[1].(*ast.Ident)
if !ok {
return
}
if txExpr.Name != "tx" {
return
}

txField := &ast.KeyValueExpr{
Key: ast.NewIdent("Transaction"),
Value: ast.NewIdent("tx"),
}

hashField := &ast.KeyValueExpr{
Key: ast.NewIdent("HashZks"),
Value: &ast.CallExpr{
Fun: &ast.SelectorExpr{
X: ast.NewIdent("tx"),
Sel: ast.NewIdent("Hash"),
},
},
}
newRet := &ast.CompositeLit{
Type: &ast.SelectorExpr{
X: ast.NewIdent("generated"),
Sel: ast.NewIdent("Transaction"),
},
Elts: []ast.Expr{txField, hashField},
}
pointerRet := &ast.UnaryExpr{Op: token.AND, X: newRet}
returnStmt.Results[1] = pointerRet
}
}
15 changes: 9 additions & 6 deletions core/gethwrappers/ccip/generated/commit_store/commit_store.go

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading

0 comments on commit 2632051

Please sign in to comment.