Distribute 200k OP from DAO vault on Optimism to tricrypto pools over 8 weeks

Summary:

Distribute 200k OP from DAO vault on Optimism to tricrypto pools over 8 weeks

Abstract:

Curve has 504,828 OP in the DAO vault on Optimism. Curve Lending has been rolling out on mainnet and Arbitrum, soon expected to deploy on Optimism. As part of the rollout, Optimism will need crvUSD pools paired with assets suitable for Curve Lending markets. There are two recently deployed tricrypto pools containing crvUSD that will be bootstrapped by distributing OP as pool incentives to LPs.

Motivation:

Bootstrap Curve Lending on Optimism.

Specification:

Call broadcast to the Optimism broadcaster, which sends an encoded cross-chain message over Optimism bridge to the relayer on Optimism. The agent transfers the stream amount (200k OP) to the streamer contract, which has been initialized with a reward duration of 4838400 (8 weeks). Then the agent adds the crvUSD/WBTC/WETH and crvUSD/OP/CRV gauges as receivers. Finally it adds the OP token as a reward token in the two gauges with the streamer set as the distributor. Anyone can call the reward streamer to distribute the streamed OP to the gauges.

The actions are encoded as follows to send the cross chain message:

def encode(sig: str, *args):
    x = web3.keccak(text=sig)[:4] + encode_single(sig[sig.find("(") :], args)
    return x.hex()


OP_TOKEN = "0x4200000000000000000000000000000000000042"
STREAMER = "0x1C8f3D9Fc486e07e3c06e91a18825a344CeeFc54"
AGENT_PROXY = "0x28c4A1Fa47EEE9226F8dE7D6AF0a41C62Ca98267"
AMOUNT_TO_STREAM = 200_000 * 10**18

GAUGES = ["0x3050a62335948e008c6241b3ef9a81a8c0613b76", "0xb280fab4817c54796f9e6147aa1ad0198cfefb41"]  # up to 8 gauges

ACTIONS = [
    ("0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff", "broadcast", [ # accept transfer ownership
        ("0xabC000d88f23Bb45525E447528DBF656A9D55bf5", encode("accept_transfer_ownership()")),
    ]),
    ("0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff", "broadcast", [ # setup streamer
        ("0xD166EEdf272B860E991d331B71041799379185D5", encode("transfer(address,address,uint256)", OP_TOKEN, AGENT_PROXY, AMOUNT_TO_STREAM)), # transfer from vault to proxy
        (OP_TOKEN, encode("approve(address,uint256)", STREAMER, AMOUNT_TO_STREAM)),  # allow the gauge streamer to transferFrom proxy
        (STREAMER, encode("notify_reward_amount(uint256)", AMOUNT_TO_STREAM)),
    ]),
    ("0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff", "broadcast", [  # set gauges as receivers on the streamer
        (STREAMER, encode("add_receiver(address)", gauge)) 
        for gauge in GAUGES
    ]),
    ("0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff", "broadcast", [  # allow streamer to deposit in the gauges
        (gauge, encode("add_reward(address,address)", OP_TOKEN, STREAMER))
        for gauge in GAUGES
    ]),
]

This produces this decoded vote output:

Call via agent (0x40907540d8a6C65c637785e8f8B742ae6b0b9968):
 ├─ To: 0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff
 ├─ Function: broadcast((address,bytes)[])
 └─ Inputs: [[['0xabC000d88f23Bb45525E447528DBF656A9D55bf5', 0xe5ea47b8]]]

Call via agent (0x40907540d8a6C65c637785e8f8B742ae6b0b9968):
 ├─ To: 0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff
 ├─ Function: broadcast((address,bytes)[])
 └─ Inputs: [[['0xD166EEdf272B860E991d331B71041799379185D5', 0xbeabacc8000000000000000000000000420000000000000000000000000000000000004200000000000000000000000028c4a1fa47eee9226f8de7d6af0a41c62ca98267000000000000000000000000000000000000000000002a5a058fc295ed000000], ['0x4200000000000000000000000000000000000042', 0x095ea7b30000000000000000000000001c8f3d9fc486e07e3c06e91a18825a344ceefc54000000000000000000000000000000000000000000002a5a058fc295ed000000], ['0x1C8f3D9Fc486e07e3c06e91a18825a344CeeFc54', 0x2834ab5d000000000000000000000000000000000000000000002a5a058fc295ed000000]]]

Call via agent (0x40907540d8a6C65c637785e8f8B742ae6b0b9968):
 ├─ To: 0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff
 ├─ Function: broadcast((address,bytes)[])
 └─ Inputs: [[['0x1C8f3D9Fc486e07e3c06e91a18825a344CeeFc54', 0x4c0e33010000000000000000000000003050a62335948e008c6241b3ef9a81a8c0613b76], ['0x1C8f3D9Fc486e07e3c06e91a18825a344CeeFc54', 0x4c0e3301000000000000000000000000b280fab4817c54796f9e6147aa1ad0198cfefb41]]]

Call via agent (0x40907540d8a6C65c637785e8f8B742ae6b0b9968):
 ├─ To: 0x8e1e5001C7B8920196c7E3EdF2BCf47B2B6153ff
 ├─ Function: broadcast((address,bytes)[])
 └─ Inputs: [[['0x3050A62335948e008C6241B3Ef9A81a8C0613B76', 0xe8de0d4d00000000000000000000000042000000000000000000000000000000000000420000000000000000000000001c8f3d9fc486e07e3c06e91a18825a344ceefc54], ['0xB280fab4817C54796F9E6147aa1ad0198CFEfb41', 0xe8de0d4d00000000000000000000000042000000000000000000000000000000000000420000000000000000000000001c8f3d9fc486e07e3c06e91a18825a344ceefc54]]]
3 Likes