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

Add Polygon zkEVM support #3

Merged
merged 14 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- run: pip install -r requirements.txt
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
- run: npm ci
- run: npm install --save-dev hardhat
- run: ape test
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ Extends the capabilities of the Curve DAO allowing it to interact with contracts
| [L2 Parameter Agent](contracts/Agent.vy) | [0x5ccbB27FB594c5cF6aC0670bbcb360c0072F6839](https://arbiscan.io/address/0x5ccbB27FB594c5cF6aC0670bbcb360c0072F6839) |
| [L2 Emergency Agent](contracts/Agent.vy) | [0x2CB6E1Adf22Af1A38d7C3370441743a123991EC3](https://arbiscan.io/address/0x2CB6E1Adf22Af1A38d7C3370441743a123991EC3) |
| [L2 Vault](contracts/Vault.vy) | [0x25877b9413Cc7832A6d142891b50bd53935feF82](https://arbiscan.io/address/0x25877b9413Cc7832A6d142891b50bd53935feF82) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0x187FE3505e56f4dA67b06564F03575cC15bE2B4d](https://arbiscan.io/address/0x187FE3505e56f4dA67b06564F03575cC15bE2B4d) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x187FE3505e56f4dA67b06564F03575cC15bE2B4d](https://arbiscan.io/address/0x187FE3505e56f4dA67b06564F03575cC15bE2B4d) |

### Testnet Deployment Steps

1. Deploy `Agent` blueprint to Arbitrum

```bash
$ ape run deploy_blueprint Agent --network https://goerli-rollup.arbitrum.io/rpc
$ ape run deploy_agent --network https://goerli-rollup.arbitrum.io/rpc
```

2. Deploy `ArbitrumRelayer` and `Vault` to Arbitrum
Expand Down Expand Up @@ -51,7 +51,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [L2 Parameter Agent](contracts/Agent.vy) | [0xE7F2B72E94d1c2497150c24EA8D65aFFf1027b9b](https://optimistic.etherscan.io/address/0xE7F2B72E94d1c2497150c24EA8D65aFFf1027b9b) |
| [L2 Emergency Agent](contracts/Agent.vy) | [0x9fF1ddE4BE9BbD891836863d227248047B3D881b](https://optimistic.etherscan.io/address/0x9fF1ddE4BE9BbD891836863d227248047B3D881b) |
| [L2 Vault](contracts/Vault.vy) | [0xD166EEdf272B860E991d331B71041799379185D5](https://optimistic.etherscan.io/address/0xD166EEdf272B860E991d331B71041799379185D5) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0xC5fd5D3b06a8ef50b911972CA313E4d327F7c0aC](https://optimistic.etherscan.io/address/0xc5fd5d3b06a8ef50b911972ca313e4d327f7c0ac) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0xC5fd5D3b06a8ef50b911972CA313E4d327F7c0aC](https://optimistic.etherscan.io/address/0xc5fd5d3b06a8ef50b911972ca313e4d327f7c0ac) |

### Testnet Deployment Steps

Expand All @@ -76,6 +76,21 @@ preferable to generate a fresh account and use it for steps 2 and 3.
Note: The `OptimismRelayer` and the `OptimismBroadcaster` need to be deployed at the same address. To do so you need to use the same nonce. It's
preferable to generate a fresh account and use it for steps 2 and 3.

## X layer

### Mainnet Deployment Addresses

| Name | Address |
|-----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| [L1 Broadcaster](contracts/optimism/PolygonzkEVMBroadcaster.vy) | [0x9D9e70CA10fE911Dee9869F21e5ebB24A9519Ade](https://etherscan.io/address/0x9D9e70CA10fE911Dee9869F21e5ebB24A9519Ade) |
| [L2 Relayer](contracts/optimism/PolygonzkEVMRelayer.vy) | [0x9D9e70CA10fE911Dee9869F21e5ebB24A9519Ade](https://www.okx.com/explorer/xlayer/address/0x9D9e70CA10fE911Dee9869F21e5ebB24A9519Ade) |
| [L2 Ownership Agent](contracts/Agent.vy) | [0x6628b9e7c0029cea234b382be17101648f32cd8f](https://www.okx.com/explorer/xlayer/address/0x6628b9e7c0029cea234b382be17101648f32cd8f) |
| [L2 Parameter Agent](contracts/Agent.vy) | [0xccc4864762412f3273bf7ca9264295909504ebb5](https://www.okx.com/explorer/xlayer/address/0xccc4864762412f3273bf7ca9264295909504ebb5) |
| [L2 Emergency Agent](contracts/Agent.vy) | [0x9ffc6f671d88593aae56d9d34f2b40d7a56d467f](https://www.okx.com/explorer/xlayer/address/0x9ffc6f671d88593aae56d9d34f2b40d7a56d467f) |
| [L2 Vault](contracts/Vault.vy) | [0x0848F3800F04b3ad4309A5f27814be7FC4740cB9](https://www.okx.com/explorer/xlayer/address/0x0848F3800F04b3ad4309A5f27814be7FC4740cB9) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x0199429171bce183048dccf1d5546ca519ea9717](https://www.okx.com/explorer/xlayer/address/0x0199429171bce183048dccf1d5546ca519ea9717) |


## Base

### Mainnet Deployment Addresses
Expand All @@ -88,7 +103,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [L2 Parameter Agent](contracts/Agent.vy) | [0x7Ea4B72f04D8B02994F4EdB171Ce5F56eEdF457F](https://basescan.org/address/0x7Ea4B72f04D8B02994F4EdB171Ce5F56eEdF457F) |
| [L2 Emergency Agent](contracts/Agent.vy) | [0x95F0f720CAdDED982E6998b3390E6D3788c2CE5C](https://basescan.org/address/0x95F0f720CAdDED982E6998b3390E6D3788c2CE5C) |
| [L2 Vault](contracts/Vault.vy) | [0xA4c0eA0fb8eb652e11C8123E589197E18Ca78AA8](https://basescan.org/address/0xA4c0eA0fb8eb652e11C8123E589197E18Ca78AA8) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0xF3BC9E5fA891977DCa765ff52E8f22A1F7d49c1f](https://basescan.org/address/0xF3BC9E5fA891977DCa765ff52E8f22A1F7d49c1f) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0xF3BC9E5fA891977DCa765ff52E8f22A1F7d49c1f](https://basescan.org/address/0xF3BC9E5fA891977DCa765ff52E8f22A1F7d49c1f) |

## Mantle

Expand All @@ -102,7 +117,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [L2 Parameter Agent](contracts/Agent.vy) | [0x024d362f7aa162d8591304016fd60a209efc527e](https://explorer.mantle.xyz/address/0x024d362f7aa162d8591304016fd60a209efc527e) |
| [L2 Emergency Agent](contracts/Agent.vy) | [0x4339b53cf7f6eec1a997ceea81165e45c1244429](https://explorer.mantle.xyz/address/0x4339b53cf7f6eec1a997ceea81165e45c1244429) |
| [L2 Vault](contracts/Vault.vy) | [0x77A214bd4ee3650e5608339BBbE04b09f5546ECF](https://explorer.mantle.xyz/address/0x77A214bd4ee3650e5608339BBbE04b09f5546ECF) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0x5EF72230578b3e399E6C6F4F6360edF95e83BBfd](https://explorer.mantle.xyz/address/0x5EF72230578b3e399E6C6F4F6360edF95e83BBfd) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x5EF72230578b3e399E6C6F4F6360edF95e83BBfd](https://explorer.mantle.xyz/address/0x5EF72230578b3e399E6C6F4F6360edF95e83BBfd) |

## Avalanche

Expand All @@ -116,7 +131,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [Parameter Agent](contracts/Agent.vy) | [0x33F9A2F3B85e7D4Ff4f9286a9a8525060100D855](https://snowtrace.io/address/0x33F9A2F3B85e7D4Ff4f9286a9a8525060100D855) |
| [Emergency Agent](contracts/Agent.vy) | [0x1309DB123020F0533aFAfaF11D26286d5871bEB0](https://snowtrace.io/address/0x1309DB123020F0533aFAfaF11D26286d5871bEB0) |
| [Vault](contracts/Vault.vy) | [0xad422855ac8010f82F08696CA7750EfE061aa6D6](https://snowtrace.io/address/0xad422855ac8010f82F08696CA7750EfE061aa6D6) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0x31d13B6e3e287F506D21bBED9eA4b169971DF3fe](https://snowtrace.io/address/0x31d13B6e3e287F506D21bBED9eA4b169971DF3fe) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x31d13B6e3e287F506D21bBED9eA4b169971DF3fe](https://snowtrace.io/address/0x31d13B6e3e287F506D21bBED9eA4b169971DF3fe) |

## Fantom

Expand All @@ -130,7 +145,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [Parameter Agent](contracts/Agent.vy) | [0x837814ba42c6f3B39f0A5060168F7027695DDAb1](https://ftmscan.com/address/0x837814ba42c6f3B39f0A5060168F7027695DDAb1) |
| [Emergency Agent](contracts/Agent.vy) | [0x42113C6818ACb87ca3CaFDbBc6a6ae396f1548E6](https://ftmscan.com/address/0x42113C6818ACb87ca3CaFDbBc6a6ae396f1548E6) |
| [Vault](contracts/Vault.vy) | [0x49C8De2D10C9A56DD9A59ab5Ca1216111276394C](https://ftmscan.com/address/0x49C8De2D10C9A56DD9A59ab5Ca1216111276394C) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0x0732539C8aD556594FDa6A50fA8E976cA6D514B9](https://ftmscan.com/address/0x0732539C8aD556594FDa6A50fA8E976cA6D514B9) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x0732539C8aD556594FDa6A50fA8E976cA6D514B9](https://ftmscan.com/address/0x0732539C8aD556594FDa6A50fA8E976cA6D514B9) |

## Binance Smart Chain

Expand All @@ -144,7 +159,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [Parameter Agent](contracts/Agent.vy) | [0x618a38a556B66FdDdcB5495Be412Df911D18eA1d](https://bscscan.com/address/0x618a38a556B66FdDdcB5495Be412Df911D18eA1d) |
| [Emergency Agent](contracts/Agent.vy) | [0xC940CE179f1F1bdC1EA1c02A2d0481bfD84C3280](https://bscscan.com/address/0xC940CE179f1F1bdC1EA1c02A2d0481bfD84C3280) |
| [Vault](contracts/Vault.vy) | [0x44C927BacD65da570cB1F0A2F625367049525022](https://bscscan.com/address/0x44C927BacD65da570cB1F0A2F625367049525022) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0x3D09c5D6AE6e45d01C560342E11ef355C2763F01](https://bscscan.com/address/0x3D09c5D6AE6e45d01C560342E11ef355C2763F01) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x3D09c5D6AE6e45d01C560342E11ef355C2763F01](https://bscscan.com/address/0x3D09c5D6AE6e45d01C560342E11ef355C2763F01) |

## Kava

Expand All @@ -157,7 +172,7 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [Ownership Agent](contracts/Agent.vy) | [0xeC6a886148B38C233B07cc6732142dccaBF1051D](https://kavascan.com/address/0xeC6a886148B38C233B07cc6732142dccaBF1051D) |
| [Parameter Agent](contracts/Agent.vy) | [0x6e53131F68a034873b6bFA15502aF094Ef0c5854](https://kavascan.com/address/0x6e53131F68a034873b6bFA15502aF094Ef0c5854) |
| [Emergency Agent](contracts/Agent.vy) | [0xA177D2bd2BD723878bD95982c0855291953f74C9](https://kavascan.com/address/0xA177D2bd2BD723878bD95982c0855291953f74C9) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0xC0AE3B85060530384647E9F3D63C9e1F53231f68](https://kavascan.com/address/0xC0AE3B85060530384647E9F3D63C9e1F53231f68) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0xC0AE3B85060530384647E9F3D63C9e1F53231f68](https://kavascan.com/address/0xC0AE3B85060530384647E9F3D63C9e1F53231f68) |

## Polygon

Expand All @@ -170,4 +185,4 @@ preferable to generate a fresh account and use it for steps 2 and 3.
| [Ownership Agent](contracts/Agent.vy) | [0x8cB05bFEd65b522a7cF98d590F1711A9Db43af71](https://polygonscan.com/address/0x8cB05bFEd65b522a7cF98d590F1711A9Db43af71) |
| [Parameter Agent](contracts/Agent.vy) | [0x3CF7c393519ea55D1E1F2c55a6395be63b1A9F9C](https://polygonscan.com/address/0x3CF7c393519ea55D1E1F2c55a6395be63b1A9F9C) |
| [Emergency Agent](contracts/Agent.vy) | [0x9FD6E204e08867170ddE54a8374083fF592eBD3E](https://polygonscan.com/address/0x9FD6E204e08867170ddE54a8374083fF592eBD3E) |
| [Agent Blueprint](scripts/deploy_blueprint.py) | [0x1fE46Da288A55aAf32facc6D182fB1933B22c2E9](https://polygonscan.com/address/0x1fE46Da288A55aAf32facc6D182fB1933B22c2E9) |
| [Agent Blueprint](scripts/deploy_agent.py) | [0x1fE46Da288A55aAf32facc6D182fB1933B22c2E9](https://polygonscan.com/address/0x1fE46Da288A55aAf32facc6D182fB1933B22c2E9) |
137 changes: 137 additions & 0 deletions contracts/polygon_zkevm/PolygonzkEVMBroadcaster.vy
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# @version 0.3.10
"""
@title Polygon zkEVM Broadcaster
@author CurveFi
"""


interface PolygonZkEVMBridge:
def bridgeMessage(destination_network: uint32, destination_address: address, force_update: bool, metadata: Bytes[MAX_MESSAGE_RECEIVED]): payable


event Broadcast:
agent: Agent
messages: DynArray[Message, MAX_MESSAGES]


event SetNewBridge:
new_bridge: PolygonZkEVMBridge


event SetNewDestinationNetwork:
new_network: uint32


event ApplyAdmins:
admins: AdminSet

event CommitAdmins:
future_admins: AdminSet


enum Agent:
OWNERSHIP
PARAMETER
EMERGENCY


struct AdminSet:
ownership: address
parameter: address
emergency: address

struct Message:
target: address
data: Bytes[MAX_BYTES]


MAX_BYTES: constant(uint256) = 1024
MAX_MESSAGES: constant(uint256) = 8
MAX_MESSAGE_RECEIVED: constant(uint256) = 9400


admins: public(AdminSet)
future_admins: public(AdminSet)

agent: public(HashMap[address, Agent])

POLYGON_ZKEVM_BRIDGE: public(immutable(PolygonZkEVMBridge))
DESTINATION_NETWORK: public(immutable(uint32))


@external
def __init__(_admins: AdminSet, _polygon_zkevm_bridge: PolygonZkEVMBridge, _destination_network: uint32):
assert _admins.ownership != _admins.parameter # a != b
assert _admins.ownership != _admins.emergency # a != c
assert _admins.parameter != _admins.emergency # b != c

self.admins = _admins

self.agent[_admins.ownership] = Agent.OWNERSHIP
self.agent[_admins.parameter] = Agent.PARAMETER
self.agent[_admins.emergency] = Agent.EMERGENCY

POLYGON_ZKEVM_BRIDGE = _polygon_zkevm_bridge
DESTINATION_NETWORK = _destination_network

log ApplyAdmins(_admins)


@external
def broadcast(_messages: DynArray[Message, MAX_MESSAGES], _force_update: bool=True):
"""
@notice Broadcast a sequence of messages.
@dev Save `depositCount` from POLYGON_ZKEVM_BRIDGE.BridgeEvent to claim message on destination chain
@param _messages The sequence of messages to broadcast.
@param _force_update Indicates if the new global exit root is updated or not (forceUpdateGlobalExitRoot)
"""
agent: Agent = self.agent[msg.sender]
assert agent != empty(Agent)

POLYGON_ZKEVM_BRIDGE.bridgeMessage(DESTINATION_NETWORK, self, _force_update,
_abi_encode( # relay(uint256,(address,bytes)[])
agent,
_messages,
method_id=method_id("relay(uint256,(address,bytes)[])"),
),
)

log Broadcast(agent, _messages)


@external
def commit_admins(_future_admins: AdminSet):
"""
@notice Commit an admin set to use in the future.
"""
assert msg.sender == self.admins.ownership

assert _future_admins.ownership != _future_admins.parameter # a != b
assert _future_admins.ownership != _future_admins.emergency # a != c
assert _future_admins.parameter != _future_admins.emergency # b != c

self.future_admins = _future_admins
log CommitAdmins(_future_admins)


@external
def apply_admins():
"""
@notice Apply the future admin set.
"""
admins: AdminSet = self.admins
assert msg.sender == admins.ownership

# reset old admins
self.agent[admins.ownership] = empty(Agent)
self.agent[admins.parameter] = empty(Agent)
self.agent[admins.emergency] = empty(Agent)

# set new admins
future_admins: AdminSet = self.future_admins
self.agent[future_admins.ownership] = Agent.OWNERSHIP
self.agent[future_admins.parameter] = Agent.PARAMETER
self.agent[future_admins.emergency] = Agent.EMERGENCY

self.admins = future_admins
log ApplyAdmins(future_admins)
84 changes: 84 additions & 0 deletions contracts/polygon_zkevm/PolygonzkEVMRelayer.vy
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# @version 0.3.10
"""
@title Polygon zkEVM Relayer
@author CurveFi
"""

event Relay:
agent: Agent
messages: DynArray[Message, MAX_MESSAGES]

event SetMessenger:
messenger: address

event SetOriginNetwork:
origin_network: uint32


interface IAgent:
def execute(_messages: DynArray[Message, MAX_MESSAGES]): nonpayable


enum Agent:
OWNERSHIP
PARAMETER
EMERGENCY


struct Message:
target: address
data: Bytes[MAX_BYTES]


MAX_BYTES: constant(uint256) = 1024
MAX_MESSAGES: constant(uint256) = 8
MAX_MESSAGE_RECEIVED: constant(uint256) = 9400
CODE_OFFSET: constant(uint256) = 3


OWNERSHIP_AGENT: public(immutable(address))
PARAMETER_AGENT: public(immutable(address))
EMERGENCY_AGENT: public(immutable(address))


agent: HashMap[Agent, address]
MESSENGER: public(immutable(address))
ORIGIN_NETWORK: public(immutable(uint32))


@external
def __init__(_agent_blueprint: address, _messenger: address, _origin_network: uint32):
MESSENGER = _messenger
log SetMessenger(_messenger)
ORIGIN_NETWORK = _origin_network

OWNERSHIP_AGENT = create_from_blueprint(_agent_blueprint, code_offset=CODE_OFFSET)
PARAMETER_AGENT = create_from_blueprint(_agent_blueprint, code_offset=CODE_OFFSET)
EMERGENCY_AGENT = create_from_blueprint(_agent_blueprint, code_offset=CODE_OFFSET)

self.agent[Agent.OWNERSHIP] = OWNERSHIP_AGENT
self.agent[Agent.PARAMETER] = PARAMETER_AGENT
self.agent[Agent.EMERGENCY] = EMERGENCY_AGENT


@external
def relay(_agent: Agent, _messages: DynArray[Message, MAX_MESSAGES]):
"""
@notice Receive messages for an agent and relay them.
@param _agent The agent to relay messages to.
@param _messages The sequence of messages to relay.
"""
assert msg.sender == self

IAgent(self.agent[_agent]).execute(_messages)

log Relay(_agent, _messages)


@external
def onMessageReceived(_origin_address: address, _origin_network: uint32, _data: Bytes[MAX_MESSAGE_RECEIVED]):
assert msg.sender == MESSENGER
assert _origin_address == self
assert _origin_network == ORIGIN_NETWORK

raw_call(self, _data) # .relay()
52 changes: 52 additions & 0 deletions contracts/polygon_zkevm/mocks/MockPolygonzkEVMBridge.vy
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# @version 0.3.10


origin_address: public(address)
destination_address: public(address)
origin_network: public(uint32)
metadata: public(Bytes[9000])

force_updated: public(bool)

count: public(uint256)


@external
def _set_origin_network(_origin_network: uint32):
self.origin_network = _origin_network

@external
def _set_origin_address(_origin_address: address):
self.origin_address = _origin_address

@external
def _set_destination_address(_destination_address: address):
self.destination_address = _destination_address


@payable
@external
def bridgeMessage(_destination_network: uint32, _destination_address: address, _force_update: bool, _metadata: Bytes[9000]):
assert _destination_network == 3, "DestinationNetworkInvalid"

self.origin_address = msg.sender
self.destination_address = _destination_address
self.metadata = _metadata

self.force_updated = _force_update

self.count += 1


@payable
@external
def claimMessage():
raw_call(
self.destination_address,
_abi_encode(
self.origin_address, self.origin_network, self.metadata,
method_id=method_id("onMessageReceived(address,uint32,bytes)"),
),
value=msg.value,
revert_on_failure=True,
)
Loading
Loading