Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding zksync wrappers #1599

Draft
wants to merge 2 commits into
base: ccip-develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading