Skip to content

Deploy CoW DAO module on mainnet#231

Open
fedgiac wants to merge 4 commits intocow-dao-modulefrom
deployment-cow-dao-module
Open

Deploy CoW DAO module on mainnet#231
fedgiac wants to merge 4 commits intocow-dao-modulefrom
deployment-cow-dao-module

Conversation

@fedgiac
Copy link
Contributor

@fedgiac fedgiac commented Nov 27, 2025

The contract introduced in #230 was deployed on mainnet. (Up-to-date as of commit e297f00.)

Deployment output:

deployment
$ yarn deploy --network mainnet
yarn run v1.22.22
$ hardhat deploy --network mainnet
Nothing to compile
reusing "AllocationModule" at 0x582A254713b65c140840ade25A692fBe2610682d
To enable this module in the team controller safe, execute a transaction with the following parameters on the team controller safe:
To: 0xca07EaA4253638D286caD71CBcEec11803F2709A
Value: 0
Data: 0x610b5925000000000000000000000000582a254713b65c140840ade25a692fbe2610682d
deploying "CowDaoAllocationModule" (tx: 0x68bf9d00ab29118d45644bb02a528a115b2b2bd9dc2b81079197535a159628dc)...: deployed at 0xd2D2946402c60d1C97195fa22eaD21812e1ff25D with 940371 gas
To enable this module in the CoW DAO safe, execute a transaction with the following parameters on CoW DAO:
To: 0xcA771eda0c70aA7d053aB1B25004559B918FE662
Value: 0
Data: 0x610b5925000000000000000000000000d2d2946402c60d1c97195fa22ead21812e1ff25d
updating 'networks.json'...
contract verification (already verified)
$ yarn verify:etherscan --network mainnet
yarn run v1.22.22
$ hardhat etherscan-verify --license LGPL-3.0 --force-license --network mainnet
already verified: AllocationModule (0x582A254713b65c140840ade25A692fBe2610682d), skipping.
already verified: CowDaoAllocationModule (0xd2D2946402c60d1C97195fa22eaD21812e1ff25D), skipping.
Done in 2.56s.

Relevant instructions to enable the module:

To enable this module in the CoW DAO safe, execute a transaction with the following parameters on CoW DAO:
To: 0xcA771eda0c70aA7d053aB1B25004559B918FE662
Value: 0
Data: 0x610b5925000000000000000000000000d2d2946402c60d1c97195fa22ead21812e1ff25d

Allocation

For completeness, we generate the expected allocation transaction in the proposal.

Generation

Using the following CSV input (2026-01-08-dao-vesting-revised.csv):

Address,Number of Tokens,Start Date,Duration (days)
0x486c2B52FfbeD401b16ce39b7Ab9E2Ebf56D650f,"50000000",2026-02-11Z08:05:15,1460

and running the script:

$ npx hardhat start-vesting --network mainnet --allocation-module 0xd2D2946402c60d1C97195fa22eaD21812e1ff25D --csv ./2026-01-08-dao-vesting-revised.csv 
┌─────────┬──────────────────────────────────────────────┬──────────────┬────────────────────┬───────────────────┬───────────────────┐
│ (index) │ Beneficiary address                          │ Amount       │ USD cost at launch │ Vesting start     │ Vesting end       │
├─────────┼──────────────────────────────────────────────┼──────────────┼────────────────────┼───────────────────┼───────────────────┤
│ 0       │ '0x486c2B52FfbeD401b16ce39b7Ab9E2Ebf56D650f' │ '50,000,000' │ '7,500,000'        │ 'Wed Feb 11 2026' │ 'Sun Feb 10 2030' │
└─────────┴──────────────────────────────────────────────┴──────────────┴────────────────────┴───────────────────┴───────────────────┘

The allocation module needs to be enabled in the team controller Safe before new vesting positions can be added.
A transaction that enables the allocation module was added at the start of the batch.

we get the following transaction builder output:

{
  "version": "1.0",
  "chainId": "1",
  "createdAt": 1767890320560,
  "meta": {
    "name": "Start Vesting Transactions Batch",
    "description": "A transaction that batches together multiple calls to the allocation modules for starting vesting positions"
  },
  "transactions": [
    {
      "to": "0xcA771eda0c70aA7d053aB1B25004559B918FE662",
      "data": "0x610b5925000000000000000000000000d2d2946402c60d1c97195fa22ead21812e1ff25d",
      "value": "0"
    },
    {
      "to": "0xd2D2946402c60d1C97195fa22eaD21812e1ff25D",
      "data": "0x02a861a6000000000000000000000000486c2b52ffbed401b16ce39b7ab9e2ebf56d650f00000000000000000000000000000000000000000000000000000000698c383b000000000000000000000000000000000000000000000000000000000784ce00000000000000000000000000000000000000000000295be96e64066972000000",
      "value": "0"
    }
  ]
}

The resulting transaction builder file is the following:

2026-01-08-cow-funding-dao-proposal.json

A simulation can be found here.

Note that it already includes the enabling of the module discussed above, meaning that this file contains the entire proposal.

(It's expected to show a warning "This batch contains some changed properties since you saved or downloaded it" since the format used lacks the checksum.)

Test Plan

Check that the verified contract code matches.

You can also compare the bytecode of 0xd2D2946402c60d1C97195fa22eaD21812e1ff25D and 0x582A254713b65c140840ade25A692fBe2610682d to confirm that there are no changes outside of the deployment parameters.

bytecode diff image

@fedgiac fedgiac requested a review from a team November 27, 2025 17:00

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth mentioning that this new solcInputs file is almost the same as the original (already checked into the main branch) save for one difference

--- deployments/mainnet/solcInputs/a646833678744341c349f0a109c850d1.json	2026-01-13 19:15:32.376531854 +0900
+++ deployments/mainnet/solcInputs/bcd8532b3dae86997a3aae16f3b66a58.json	2026-01-13 19:04:32.597336281 +0900
@@ -7,9 +7,6 @@
     "src/contracts/interface/CowProtocolTokens.sol": {
       "content": "// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity ^0.8;\n\n/// @dev Interface exposing some of the functions of the governance token for the CoW Protocol.\n/// @title CoW Protocol Governance Token Minimal Interface\n/// @author CoW Protocol Developers\ninterface CowProtocolToken {\n    /// @dev Moves `amount` tokens from the caller's account to `to`.\n    /// Returns true. Reverts if the operation didn't succeed.\n    function transfer(address to, uint256 amount) external returns (bool);\n}\n\n/// @dev Interface exposing some of the functions of the virtual token for the CoW Protocol.\n/// @title CoW Protocol Virtual Token Minimal Interface\n/// @author CoW Protocol Developers\ninterface CowProtocolVirtualToken {\n    /// @dev Converts an amount of (virtual) tokens from this contract to real\n    /// tokens based on the claims previously performed by the caller.\n    /// @param amount How many virtual tokens to convert into real tokens.\n    function swap(uint256 amount) external;\n\n    /// @dev Address of the real COW token. Tokens claimed by this contract can\n    /// be converted to this token if this contract stores some balance of it.\n    function cowToken() external view returns (address);\n}\n"
     },
-    "src/contracts/test/MockVCow.sol": {
-      "content": "// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity ^0.8;\n\n/// @dev Mock of vCOW token. Emits an event when calling `swap`.\n/// @title vCOW mock contract\n/// @author CoW Protocol Developers\ncontract MockVcow {\n    address public cowToken;\n\n    constructor(address _cowToken) {\n        cowToken = _cowToken;\n    }\n\n    event Swapped(address caller, uint256 amount);\n\n    function swap(uint256 amount) external {\n        emit Swapped(msg.sender, amount);\n    }\n}\n"
-    },
     "src/contracts/vendored/Enum.sol": {
       "content": "// SPDX-License-Identifier: LGPL-3.0-only\n\n// Vendored from @gnosis.pm/safe-contracts v1.3.0, see:\n// <https://raw.githubusercontent.com/gnosis/safe-contracts/v1.3.0/contracts/common/Enum.sol>\n\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - <[email protected]>\ncontract Enum {\n    enum Operation {\n        Call,\n        DelegateCall\n    }\n}\n"
     },

I think functionally its the same as what ends up on mainnet down to the CBOR, but wouldn't it be nice to reuse the existing artifact?

Copy link

@kaze-cow kaze-cow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inclusion of the solcInputs file was a bit surprising to me as the inputs should be the same, but turns out there is one small difference in the inclusion of the MockVCow test file in the compilation output. I don't think this harms anything, but interesting to see.

deployment itself seems good. initcode is the same as the original deployment except for the Safe address, and addresses match up.

Copy link

@anxolin anxolin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everytying worked as described in the instructions. Thanks for the detailed steps and setting expectations!

ubernit: not from this PR, but I wish start-vesting would have written the output file nam in the console log. I check in the script cause at first I didn't know where to look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments