Skip to content

Commit

Permalink
Merge pull request #216 from metagov/feat/optimism_eas
Browse files Browse the repository at this point in the history
feat: optimize op eas register.
  • Loading branch information
crazyyuan authored Mar 26, 2024
2 parents 7031a08 + f5bab9f commit 354ef36
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 23 deletions.
144 changes: 144 additions & 0 deletions daostar-website/src/abi/EASRegistrationContract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
const EASRegistrationContract = [{
"inputs": [{"internalType": "address", "name": "_admin", "type": "address"}],
"stateMutability": "nonpayable",
"type": "constructor"
}, {
"anonymous": false,
"inputs": [{"indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"indexed": true,
"internalType": "bytes32",
"name": "previousAdminRole",
"type": "bytes32"
}, {"indexed": true, "internalType": "bytes32", "name": "newAdminRole", "type": "bytes32"}],
"name": "RoleAdminChanged",
"type": "event"
}, {
"anonymous": false,
"inputs": [{"indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
}, {"indexed": true, "internalType": "address", "name": "sender", "type": "address"}],
"name": "RoleGranted",
"type": "event"
}, {
"anonymous": false,
"inputs": [{"indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
}, {"indexed": true, "internalType": "address", "name": "sender", "type": "address"}],
"name": "RoleRevoked",
"type": "event"
}, {
"inputs": [],
"name": "DEFAULT_ADMIN_ROLE",
"outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32"}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [],
"name": "MEMBER_ROLE",
"outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32"}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [{
"components": [{
"internalType": "bytes32",
"name": "uid",
"type": "bytes32"
}, {"internalType": "bytes32", "name": "schema", "type": "bytes32"}, {
"internalType": "uint64",
"name": "time",
"type": "uint64"
}, {"internalType": "uint64", "name": "expirationTime", "type": "uint64"}, {
"internalType": "uint64",
"name": "revocationTime",
"type": "uint64"
}, {"internalType": "bytes32", "name": "refUID", "type": "bytes32"}, {
"internalType": "address",
"name": "recipient",
"type": "address"
}, {"internalType": "address", "name": "attester", "type": "address"}, {
"internalType": "bool",
"name": "revocable",
"type": "bool"
}, {"internalType": "bytes", "name": "data", "type": "bytes"}],
"internalType": "struct Attestation",
"name": "attestation",
"type": "tuple"
}],
"name": "createFromEAS",
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32"}],
"name": "getRoleAdmin",
"outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32"}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [{"internalType": "address", "name": "to", "type": "address"}],
"name": "grantMember",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}, {
"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"internalType": "address",
"name": "account",
"type": "address"
}], "name": "grantRole", "outputs": [], "stateMutability": "nonpayable", "type": "function"
}, {
"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"internalType": "address",
"name": "account",
"type": "address"
}],
"name": "hasRole",
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"internalType": "address",
"name": "account",
"type": "address"
}], "name": "renounceRole", "outputs": [], "stateMutability": "nonpayable", "type": "function"
}, {
"inputs": [],
"name": "resolver",
"outputs": [{"internalType": "address", "name": "", "type": "address"}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [{"internalType": "address", "name": "to", "type": "address"}],
"name": "revokeMember",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}, {
"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32"}, {
"internalType": "address",
"name": "account",
"type": "address"
}], "name": "revokeRole", "outputs": [], "stateMutability": "nonpayable", "type": "function"
}, {
"inputs": [{"internalType": "address", "name": "_resolver", "type": "address"}],
"name": "setResolver",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}, {
"inputs": [{"internalType": "bytes4", "name": "interfaceId", "type": "bytes4"}],
"name": "supportsInterface",
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "view",
"type": "function"
}];

export default EASRegistrationContract;
9 changes: 5 additions & 4 deletions daostar-website/src/components/Register/Register.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,28 @@ const Register = (props) => {

const [registrationScreen, setRegistrationScreen] = useState('REGISTER'); // REGISTER | REG_RECEIVED
const onToggleRegScreen = (screen) => setRegistrationScreen(screen);

const [registrationData, setRegistrationData] = useState(null);

return (
<div>
<div className='centered-wizard'>
<Card className='wizard-card'>
{registrationScreen === 'REGISTER' && (
<RegistrationForm
<RegistrationForm
toggleRegScreen={onToggleRegScreen}
setRegistrationData={setRegistrationData}
/>
)}
{registrationScreen === 'REG_RECEIVED' && (
<RegistrationReceived {...registrationData} />
)}

</Card>
</div>
</div>

)
}

export default Register;
export default Register;
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import {
HTMLSelect,
InputGroup,
Switch,
Dialog, DialogBody, DialogFooter,AnchorButton
} from "@blueprintjs/core";
import { Tooltip2 } from "@blueprintjs/popover2"
import FRAMEWORK_URIs from "./FRAMEWORK_URIs";
import { EAS, SchemaEncoder } from "@ethereum-attestation-service/eas-sdk";
import { useSigner } from "../../../utils/wagmi-utils";
import { useAccount, useNetwork } from "wagmi";
import { useAccount, useNetwork, useContractRead } from "wagmi";
import { ethers } from 'ethers';

import RegistrationContract from "../../../abi/EASRegistrationContract";

const networkIds = {
mainnet: 1,
Expand All @@ -28,6 +33,8 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
const {address,isConnected} = useAccount();
const signer = useSigner();
const {chain} = useNetwork();
const [showEASRegisterDialog, setShowEASRegisterDialog] = useState(false);
const [attestationURL, setAttestationURL] = useState('');

const [daoContractNetwork, setDaoContractNetwork] = useState("mainnet");
const onChangeDaoContractNetwork = (e) => {
Expand Down Expand Up @@ -273,15 +280,17 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
errors.push(`Please connect wallet`);
}
if(!(chain.id === 10 || chain.id === 11155420)) {
errors.push(`Just support for Optimism`);
errors.push(`Switch to Optimism mainnet`);
}

// todo optimism eas schema
let easscanURL = ''
let schemaUid = '';
let registrationContract = '';
if(chain.id === 11155420) {
easscanURL = "https://optimism-sepolia.easscan.org/schema/view";
schemaUid = '0xf90c716cef83b64e4b9cbf5babeb4ee65662e2081535afd76cad37dde744c2dd';
registrationContract = '0xF124Aca94e664Bfd5373feA9E2410FD799a8a08B'
}

if (errors.length > 0) {
Expand All @@ -291,8 +300,24 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
setErrors(null);
}

// test
// setAttestationURL(`${easscanURL}/${schemaUid}`);
// setShowEASRegisterDialog(true);
// return;

setRegisterLoading(true);

// check authority
const contract = new ethers.Contract(registrationContract, RegistrationContract, signer);
const memberRole = await contract.MEMBER_ROLE();
const isMember = await contract.hasRole(memberRole,address);

if(!isMember) {
setErrors(['you have no authorization']);
setRegisterLoading(false);
return;
}

const schemaEncoder = new SchemaEncoder("string daoName,string daoURI");
const data = [
{ name: 'daoName', value: daoName, type: 'string' },
Expand All @@ -303,23 +328,32 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
const eas = new EAS('0x4200000000000000000000000000000000000021');
eas.connect(signer);

const attestation = await eas.attest({
schema: schemaUid,
data: {
recipient: address,
expirationTime: 0,
revocable: true,
refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
data: encodedData,
value: 0,
},
});
console.log("attest:",attestation);
setRegisterLoading(false);

window.location.href = `${easscanURL}/${schemaUid}`;
try {
const attestation = await eas.attest({
schema: schemaUid,
data: {
recipient: address,
expirationTime: 0,
revocable: true,
refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
data: encodedData,
value: 0,
},
});
setAttestationURL(`${easscanURL}/${schemaUid}`);
setShowEASRegisterDialog(true);
} catch (e) {
console.log("attest error:",e);
setErrors([`Register Error. ${e}`]);
} finally {
setRegisterLoading(false);
}
};

const onHandleCloseEASRegisterDialog = () => {
setShowEASRegisterDialog(false);
}

const EthNetworksSelect = (
<HTMLSelect
style={{ minWidth: 140 }}
Expand Down Expand Up @@ -531,7 +565,7 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
</div>
</div>
)}
{registerByEAS && (
{registerByEAS && !showEASRegisterDialog && (
<div style={{width:'100%'}}>
<div className="wizard-row">
<FormGroup label="DAO Name" labelFor="dao-name" fill>
Expand All @@ -555,7 +589,15 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
/>
</FormGroup>
</div>
<div className="wizard-row wizard-center">
<div style={{display:"flex", justifyContent:'space-between', margin: '40px 24px'}}>
<AnchorButton
href={`https://docs.daostar.org/How%20To's/DifferentPaths`}
target="_blank"
icon="link"
text='Get More Details'
small={true}
fill={false}
/>
<Button
intent="primary"
text="Register"
Expand All @@ -565,6 +607,28 @@ const RegistrationForm = ({ toggleRegScreen, setRegistrationData }) => {
</div>
</div>
)}
{registerByEAS && showEASRegisterDialog && (
<div style={{ width:'100%'}}>
<div style={{margin:"40px 24px",display:"flex",justifyContent:"center"}}>
<p style={{fontSize:"15px"}}>
<strong>
Congratulations, DAO registered.
</strong>
</p>
</div>
<div style={{margin:"60px 24px",display:"flex",justifyContent:"center"}}>
<AnchorButton
intent="primary"
href={attestationURL}
target="_blank"
icon="share"
fill={false}
>
View onchain
</AnchorButton>
</div>
</div>
)}

</Fragment>
);
Expand Down

0 comments on commit 354ef36

Please sign in to comment.