A Python command-line tool for deploying schemas and creating attestations using the On & Offchain Attestation DAO Protocol with Ethereum Attestation Service (EAS).
The protocol works using a collection of verbs, mixed with resolvers to handle the double-spend problem and voting window of decentralized voting.
X - INSTANTIATE
X - PERMA_INSTANTIATE
X - GRANT
X - CREATE_PROPOSAL_TYPE
O - CREATE_PROPOSAL
X - CHECKED_PROPOSAL
X - SET_PROPOSAL_TYPE
X - SET_PARAM_VALUE
V - DELEGATED_SIMPLE_VOTE
V - DELEGATED_ADVANCED_VOTE
V - SIMPLE_VOTE
V - ADVANCED_VOTE
X - DELETE
X - BADGE_DEFINITION
X - IDENTITY_BADGE
This CLI wraps Foundry's forge commands to simplify interaction with the DAO governance protocol defined in protocol.md.
0xf246C55a4f91f08c991F566fcF063156f67e6c03
0x8D7512290251bd5417A00730aBFA0E5fdba1094A
0x576c9f4C976e2E6AF9E7093F1A23Fa31B21D4cB3
0x4Ee4b7e6eE98e0b5361dACcF9062733858c4B066
0x7106847Cc6c99E3D730D4f2a8312A905c0ad2ad7
0xe84969F17B2628C71B421d552450b7F131bE07A2
0xC8EA7C7651245728BE57c2d4C5638F8eF843b0E7
0xaFb13914085154869a6770d6bbcE1Cc9B3aDE560
0xEF28EB0D4186E5795ddD25E792697abFBabceC42
0x458fAdE53C9a7186b4f097527ee1441eBD8ecAD5
0x83e02A6b7DA88d78a90Bdf7C0B8a9dd93624801c
0xE6fDeEfD25c6973d57AA7757BA546027625c40a4
0x2829EE5e93cD1671140D8AE1fe7524Ba1F5AC6ad
0xeb4Ceb297f180057CD6616d0FC5077Be795d6683
0x3d0Ee8700f3A2267a677504FfEdAE54A15ABBE7B
0x8e1892c1Eb9a2E20df90f9d55f25e765542c6790
{
'INSTANTIATE' : '0x4564d3a746bafcf78838969daaff3ba173e9f5ab73ac3023ea98dd9220953e75',
'PERMA_INSTANTIATE' : '0xc825cf97f111a55edfb1bec7b6b624dae6ccab74a3a3a42f89891dfb0d06137b',
'GRANT' : '0x8c6e4ae96424697731fd6aaa20b759a25684af059a23ba1b6aa48a12c21fd5d7',
'CREATE_PROPOSAL_TYPE' : '0xab4e473a3f8a0a0a490619bcd2ecf23ad1be4720d4033fa16f2d1cbd1519caa1',
'CREATE_PROPOSAL' : '0x38bfba767c2f41790962f09bcf52923713cfff3ad6d7604de7cc77c15fcf169a',
'CHECK_PROPOSAL' : '0x80155c3a8c4ea17ce96e8899f7ab1ceca9e85382d7f893619a1d03947a70f844',
'SET_PROPOSAL_TYPE' : '0x0519039455b478a51b33c82934bf28814f5755f6bb21c20fc47fd98c2a3fafa3',
'SET_PARAM_VALUE' : '0x5c27757206150b56764617513558234fc12ab9bb64eee71afb525fa9689c4842',
'DELEGATED_SIMPLE_VOTE' : '0x59bad5b0800beda0617b1d883711be28f8a0e619ef549310bfa6432ba64ab399',
'DELEGATED_ADVANCED_VOTE' : '0xfcff350666dcf68a382ea5e22ac4529915312b29f3bfe5a070424dcc781e354e',
'SIMPLE_VOTE' : '0x12cd8679de42e111a5ece9f2aee44dc8b8351024dea881cda97c2ff5b58349f6',
'ADVANCED_VOTE' : '0xc4465af5d96b474b1c7a6418500461d3de1fc35552679bf695eb2b3124817dce',
'DELETE' : '0x8c97e2700d9a3e52e76a4bf3c42b5a5d178f193cb14f6e2ddbc6db4ed1eae767',
}
{
'INSTANTIATE' : '0xa45718ef6b8758277682e9914ed85b960e19fd8331ed75e24641d228b7efcd2d',
'PERMA_INSTANTIATE' : '0x3921c650e5c0a565fe4e2b5dad38546999588bd18904a3354641ca6c998f6bc4',
'GRANT' : '0xd430f8dc7a9503e92e621503eed2c716a524604be530842601d7fb0e1bb8ff15',
'CREATE_PROPOSAL_TYPE' : '0x4147434e77680f972dcaa494427b876fa0f5ecdfde56131dd24a988ad90a6950',
'CREATE_PROPOSAL' : '0x38bfba767c2f41790962f09bcf52923713cfff3ad6d7604de7cc77c15fcf169a',
'CHECK_PROPOSAL' : '0x08df8e6e629077cabef4ed15cd4ff4f2359c2a60ad65b8355ac1f905b8f23a6f',
'SET_PROPOSAL_TYPE' : '0xa6ca209ead271e33d86bf969fb5b9d5f559bf3fb22765ede70652b1faa4973b5',
'SET_PARAM_VALUE' : '0xa1e21d322b14d3d79bd697b106b7374e19a61eb766907ef27d392dd635d9642f',
'DELEGATED_SIMPLE_VOTE' : '0x291f9b12f6624076505cb07cc62acf79bd7403cceb435e91d279dcbe6336c94b',
'DELEGATED_ADVANCED_VOTE' : '0xd9a51aa77ea609950350db55093af36e4c0dce621a131164cb7b410b9c2435bc',
'SIMPLE_VOTE' : '0x19c36b80a224c4800fd6ed68901ec21f591563c8a5cb2dd95382d430603f91ff',
'ADVANCED_VOTE' : '0x991b014c62b19364882fc89dbf3baa6104b4598ee2c4f29152be2cbcfcb4cb81',
'DELETE' : '0x2c451b53c595d44441eb1e8242912a0446e7bfc5f745535537908bef47e6e334',
'BADGE_DEFINITION': '0x44c0a23e342cc3b74cae094dd9be5b38447ec67045ccea4868c74d6387a52fca',
'IDENTITY_BADGE': '0x0b9dd04e9927bd43e11ddd02c31a971859ffc23abed1a0eb226fa13bfd5046d4',
}
{
'INSTANTIATE' : '0xbab63b7b41b5350afcf392b0f5b6031ea8990a6fee079ef523851ee28a4a7b74',
'PERMA_INSTANTIATE' : '0x07654386b9800935560f841794e1c5a080641e75ebc6b619e4bcec0ef7b5f11a',
'GRANT' : '0x690c13b37802f0914b28e851844e0a438aba961a9aae089a6c2a5c8a9ff0cff8',
'CREATE_PROPOSAL_TYPE' : '0xf3f87e20caefe2aac522d0eae399b03851c32d28840979c6e47c4575be2b089a',
'CREATE_PROPOSAL' : '0x38bfba767c2f41790962f09bcf52923713cfff3ad6d7604de7cc77c15fcf169a',
'CHECK_PROPOSAL' : '0xe8d4638f7eb0d8d480f81365b9fe99a9826dd42a012f0ecd3e3621bfe1602b41',
'SET_PROPOSAL_TYPE' : '0xd9a4856778d6c4ad4f692f5e498bc757f96890c101bcbf5b76b847604929fb50',
'SET_PARAM_VALUE' : '0x8e20525ba72e66262408abc256801c048b7291e6801bd3f0612c5dd72d33f74a',
'DELEGATED_SIMPLE_VOTE' : '0x3b3bc4228e669275d8d6abc1a4ff89272a92c1b9beef65e994d3cb7235d15094',
'DELEGATED_ADVANCED_VOTE' : '0xf96a60e6afdf11ceb32d2a5f79c2556f35d58f925bae955acbca20b93ed81361',
'SIMPLE_VOTE' : '0x72edbb9603b8ff8ae5310c1d33912f4a7998bea0c03afc0e06a64e41d32b78b9',
'ADVANCED_VOTE' : '0xadeeda60a3496bacee2d9fb250dc3b2af802d2623feb31e211cfc8f210119fea',
'DELETE' : '0x9b33510be4b823ffbaa2c55e9e5b2762c37a32361c24289655d35bef1ecd7b9b',
'BADGE_DEFINITION' : '0x37b439c809cec771782b95da77af9d1ed1724fe5d4ce14bce55b5b8c2373fe30',
'IDENTITY_BADGE' : '0x29283083ab37d4c00e1f2186492d9df145e9648229da70810c36da04f35c2e13',
}
{
'INSTANTIATE' : '0x91b236556a1503af427e3eac950b37f19c22d4e975b72aec520212261902b102',
'PERMA_INSTANTIATE' : '0xec89a693c93a79b17cb778fe793fa1a26f040954eb8bd4b99fe5cb5a06bf631c',
'GRANT' : '0x98bea12de475e8ad6a74b7ccaea65ade03615da82cc6dc2fe51a9d7492986942',
'CREATE_PROPOSAL_TYPE' : '0xd2c361729c5542fb5821b5d2e786ea961611f5483943ff705d0bbd5b8fb75712',
'CREATE_PROPOSAL' : '0x38bfba767c2f41790962f09bcf52923713cfff3ad6d7604de7cc77c15fcf169a',
'CHECK_PROPOSAL' : '0xfec5cd334991ff965ed91167c7542028aaedacd12e33e828097718d1616bf6d5',
'SET_PROPOSAL_TYPE' : '0xef9cc3898fd4664f66c37158a7888fa6d43c2e701db83603c9a63be8249d72f6',
'SET_PARAM_VALUE' : '0x481be5d3cfd5551ce60aa6c8e66b1cc2f960ee7a0700e5a6d00ab2183390b5eb',
'DELEGATED_SIMPLE_VOTE' : '0xebdb46abcca3042ac41c8eb5c9ce67639443b0f756145fe226bf6456e008900d',
'DELEGATED_ADVANCED_VOTE' : '0x5b439cb5cb1598b4906f69f3b48b0de0b5987ccfff0f35fbad109d349307ced0',
'SIMPLE_VOTE' : '0xa75b4e232ed088242e7ed3ec4e2f7c05836ed48fa4859febe7e505972345abc6',
'ADVANCED_VOTE' : '0x968d2abd9840871fc61e0f5fc267e2f16ea29b11cebc1aae33056d0cce79582d',
'DELETE' : '0xb4916db80e2576f3b43279838d120c35cb70f933595ac1228fac97a49d58115d',
'BADGE_DEFINITION' : '0xaa192e7d4d23ded5ce0d883324276131253880ae37f72dc5997327f9bae33d35',
'IDENTITY_BADGE' : '0xcfa6d9f1417bdef7b4d77f2e2259da4a6356a3e445fc299a9aef3834e9f4031a',
}
- Python 3.7+
- Foundry (forge)
- Install Python dependencies:
pip install -r requirements.txt- Configure environment variables:
cp .env.example .envEdit .env with your values:
CHAIN_ID=11155111 # Network chain ID
RPC_URL=https://ethereum-sepolia-rpc.publicnode.com # RPC endpoint
FORGE_ACCOUNT=default # Forge account name- Make the CLI executable (optional):
chmod +x eas_cli.pyDeploy a schema for an attestation type:
./eas_cli.py deploy <ATTESTATION_COMMAND>Examples:
./eas_cli.py deploy INSTANTIATE
./eas_cli.py deploy GRANT
./eas_cli.py deploy CREATE_PROPOSAL_TYPECreate an attestation with the specified arguments:
./eas_cli.py attest <ATTESTATION_COMMAND> <args...>Arguments must match the schema field order defined in protocol.md.
Deploy the INSTANTIATE schema:
./eas_cli.py deploy INSTANTIATECreate an INSTANTIATE attestation:
./eas_cli.py attest INSTANTIATE \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
"v0.1.0" \
"My DAO"Schema: bytes32 dao_uuid, string protocol_version, string name
Deploy the GRANT schema:
./eas_cli.py deploy GRANTGrant CREATE_PROPOSAL permission to an address:
./eas_cli.py attest GRANT \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xABCDEF1234567890ABCDEF1234567890ABCDEF12 \
"CREATE_PROPOSAL" \
7 \
""Schema: bytes32 dao_uuid, address subject, string permission, uint8 level, string filter
Permission levels (bitmask):
- Bit 0 (1): CREATE
- Bit 1 (2): REVOKE
- Bit 2 (4): UNDO
- Example:
7(binary 111) = CREATE + REVOKE + UNDO
Deploy the CREATE_PROPOSAL_TYPE schema:
./eas_cli.py deploy CREATE_PROPOSAL_TYPEDefine a gov-proposal proposal type:
./eas_cli.py attest CREATE_PROPOSAL_TYPE \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 \
"gov-proposal" \
'{"quorum": "50%", "threshold": "majority"}'Schema: bytes32 dao_uuid, bytes32 proposal_type_uuid, string class, string kwargs
Supported classes: gov-proposal, tempcheck
Deploy the CREATE_PROPOSAL schema:
./eas_cli.py deploy CREATE_PROPOSALSubmit a standard proposal:
./eas_cli.py attest CREATE_PROPOSAL \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 \
0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 \
"Treasury Allocation" \
"Allocate 100 ETH to development fund" \
1704067200 \
1704153600 \
'{"voting_module": "standard"}'Submit an approval proposal:
./eas_cli.py attest CREATE_PROPOSAL \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 \
0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 \
"Treasury Allocation" \
"Allocate 100 ETH to development fund" \
1704067200 \
1704153600 \
'{"voting_module": "approval", "choices": ["A", "B", "C"], "max_approvals": 2, "criteria": "TOP_CHOICES", "criteria_value": 2}'Submit an optimistic proposal:
./eas_cli.py attest CREATE_PROPOSAL \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 \
0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 \
"Treasury Allocation" \
"Allocate 100 ETH to development fund" \
1704067200 \
1704153600 \
'{"voting_module": "optimistic"}'Schema: bytes32 dao_uuid, bytes32 proposal_uuid, bytes32 proposal_type_uuid, string title, string description, uint64 startts, uint64 endts, string kwargs
kwargs:
kwargs is a JSON-encoded blob that allows clients to express richer proposal configuration without changing the onchain schema. This is where you specify details needed to support different proposal classes such as approval, and optimistic voting.
Timestamps: POSIX timestamps in seconds (UTC)
Deploy the SIMPLE_VOTE schema:
./eas_cli.py deploy SIMPLE_VOTEVote on a proposal:
./eas_cli.py attest SIMPLE_VOTE \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 \
0xVOTER_ADDRESS \
1 \
"I support this allocation" \
1000000000000000000Schema: bytes32 dao_uuid, bytes32 proposal_uuid, address voter, int8 choice, string reason, uint256 weight
Vote choices:
1= For-1= Against0= Abstain
Deploy the ADVANCED_VOTE schema:
./eas_cli.py deploy ADVANCED_VOTEVote with complex choice data:
./eas_cli.py attest ADVANCED_VOTE \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 \
0xVOTER_ADDRESS \
'{"option_a": 60, "option_b": 40}' \
"Split vote based on priorities" \
1000000000000000000Schema: bytes32 dao_uuid, bytes32 proposal_uuid, address voter, string choice, string reason, uint256 weight
Deploy the UNDO schema:
./eas_cli.py deploy UNDORetroactively nullify an attestation:
./eas_cli.py attest UNDO \
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
0xATTESTATION_UID_TO_UNDOSchema: bytes32 dao_uuid, bytes32 uid
Note: UNDO retroactively invalidates attestations. Requires UNDO permission (bit 2 in GRANT level).
For complete protocol specification, security considerations, and governance flow details, see protocol.md.
- dao_uuid: Unique identifier for a DAO (bytes32)
- Permissions: Authority delegated via GRANT attestations
- Proposal Types: Classes that define voting rules (gov-proposal, tempcheck)
- Timestamps: POSIX seconds since epoch (UTC)
- Platform issues
INSTANTIATEto create DAO - Initial authority grants
CREATE_PROPOSAL_TYPEpermission to council - Council member creates proposal type via
CREATE_PROPOSAL_TYPE - Delegates create proposals via
CREATE_PROPOSAL - Members vote via
SIMPLE_VOTEorADVANCED_VOTE - Results tallied offchain (or onchain with custom resolvers)
- If needed, authorized actors can issue
UNDOto nullify attestations
Open source under the protocol defined in protocol.md.