Skip to content

Commit 33cab65

Browse files
committed
manual timelocked token trust
subgraph mapping code reuse configures an slcs2 contract 🤷 uses yaml refs to reuse slsc handlers Signed-off-by: Stefan Adolf <[email protected]>
1 parent ded1b66 commit 33cab65

File tree

6 files changed

+123
-120
lines changed

6 files changed

+123
-120
lines changed

script/prod/RolloutV25Sale.sol

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy
77
import { IPNFT } from "../../src/IPNFT.sol";
88
import { IPermissioner, TermsAcceptedPermissioner } from "../../src/Permissioner.sol";
99
import { StakedLockingCrowdSale } from "../../src/crowdsale/StakedLockingCrowdSale.sol";
10-
import { LockingCrowdSale, ITrustedLockingContracts } from "../../src/crowdsale/LockingCrowdSale.sol";
10+
import { LockingCrowdSale } from "../../src/crowdsale/LockingCrowdSale.sol";
1111
import { TimelockedToken } from "../../src/TimelockedToken.sol";
1212

1313
contract RolloutV25Sale is Script {
@@ -33,17 +33,15 @@ contract RolloutV25LockingSale is Script {
3333
//mainnet 0xCfA0F84660fB33bFd07C369E5491Ab02C449f71B;
3434
address moleculeDevMultisig = 0x9d5a6ae551f1117946FF6e0e86ef9A1B20C90Cb0;
3535

36-
ITrustedLockingContracts stakedLockingCrowdsale = ITrustedLockingContracts(0xd1cE2EA7d3b0C9cAB025A4aD762FC00315141ad7);
3736
TimelockedToken timelockedTokenImplementation = TimelockedToken(0xF8F79c1E02387b0Fc9DE0945cD9A2c06F127D851);
3837

3938
vm.startBroadcast();
4039
LockingCrowdSale lockingCrowdsale = new LockingCrowdSale(timelockedTokenImplementation);
41-
lockingCrowdsale.trustLockingContractSource(stakedLockingCrowdsale);
4240
lockingCrowdsale.transferOwnership(moleculeDevMultisig);
4341
vm.stopBroadcast();
4442

4543
console.log("LOCKING_CROWDSALE_ADDRESS=%s", address(lockingCrowdsale));
46-
//console.log("timelocked token implementation=%s", address(timelockedTokenImplementation));
44+
console.log("timelocked token implementation=%s", address(timelockedTokenImplementation));
4745
// 0x7c36c64DA1c3a2065074caa9C48e7648FB733aAB
4846
// vestedDaoToken.grantRole(vestedDaoToken.ROLE_CREATE_SCHEDULE(), address(stakedLockingCrowdSale));
4947
// stakedLockingCrowdSale.trustVestingContract(vestedDaoToken);

src/crowdsale/LockingCrowdSale.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ contract LockingCrowdSale is CrowdSale {
4545
* @notice allows the owner to trust a timelocked token contract for a specific underlying token so it's not registered again.
4646
*
4747
* @param token the underlying token
48-
* @param _lockingContract the timelocked token contract to trust
48+
* @param _timelockedToken the timelocked token contract to trust
4949
*/
50-
function trustLockingContract(IERC20 token, TimelockedToken _lockingContract) public onlyOwner {
51-
lockingContracts[address(token)] = _lockingContract;
50+
function trustLockingContract(IERC20 token, TimelockedToken _timelockedToken) public onlyOwner {
51+
lockingContracts[address(token)] = _timelockedToken;
5252
}
5353

5454
/**

subgraph/networks.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
"address": "0xd1cE2EA7d3b0C9cAB025A4aD762FC00315141ad7",
2525
"startBlock": 5300777
2626
},
27+
"StakedLockingCrowdSale2": {
28+
"address": "0xbaadf00dbaadf00dbaadf00dbaadf00dbaadf00d",
29+
"startBlock": 7306191
30+
},
2731
"TermsAcceptedPermissioner": {
2832
"address": "0xC05D649368d8A5e2E98CAa205d47795de5fCB599",
2933
"startBlock": 5300776
@@ -54,6 +58,10 @@
5458
"address": "0x35Bce29F52f51f547998717CD598068Afa2B29B7",
5559
"startBlock": 17481804
5660
},
61+
"StakedLockingCrowdSale2": {
62+
"address": "0xbaadf00dbaadf00dbaadf00dbaadf00dbaadf00d",
63+
"startBlock": 21431344
64+
},
5765
"TermsAcceptedPermissioner": {
5866
"address": "0xC837E02982992B701A1B5e4E21fA01cEB0a628fA",
5967
"startBlock": 17790450
@@ -84,6 +92,10 @@
8492
"address": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
8593
"startBlock": 0
8694
},
95+
"StakedLockingCrowdSale2": {
96+
"address": "0xbaadf00dbaadf00dbaadf00dbaadf00dbaadf00d",
97+
"startBlock": 0
98+
},
8799
"TermsAcceptedPermissioner": {
88100
"address": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
89101
"startBlock": 0

subgraph/src/lockingCrowdSaleMapping.ts

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import {
22
BigInt,
33
Bytes,
44
DataSourceContext,
5-
log,
6-
ethereum
5+
log
76
} from '@graphprotocol/graph-ts'
87
import { IERC20Metadata } from '../generated/CrowdSale/IERC20Metadata'
98

@@ -13,7 +12,7 @@ import { handleStarted as plainHandleStarted } from './crowdSaleMapping'
1312

1413
import * as GenericCrowdSale from './genericCrowdSale'
1514

16-
import { Contribution, CrowdSale, ERC20Token, IPT } from '../generated/schema'
15+
import { CrowdSale, ERC20Token, IPT } from '../generated/schema'
1716

1817
import { TimelockedToken as TimelockedTokenTemplate } from '../generated/templates'
1918
import { makeERC20Token, makeTimelockedToken } from './common'
@@ -29,25 +28,7 @@ import {
2928
Started as StartedEvent
3029
} from '../generated/LockingCrowdSale/LockingCrowdSale'
3130

32-
export function handleStarted(event: StartedEvent): void {
33-
const _plain = new PlainStartedEvent(
34-
event.address,
35-
event.logIndex,
36-
event.transactionLogIndex,
37-
event.logType,
38-
event.block,
39-
event.transaction,
40-
[
41-
event.parameters[0],
42-
event.parameters[1],
43-
event.parameters[2],
44-
event.parameters[5]
45-
],
46-
event.receipt
47-
)
48-
49-
plainHandleStarted(_plain)
50-
31+
export function lockingHandleStarted(event: StartedEvent): void {
5132
let crowdSale = CrowdSale.load(event.params.saleId.toString())
5233
if (!crowdSale) {
5334
log.error('[Crowdsale] Creation failed for: {}', [
@@ -81,11 +62,32 @@ export function handleStarted(event: StartedEvent): void {
8162
crowdSale.amountStaked = BigInt.fromU32(0)
8263
crowdSale.auctionLockingDuration = event.params.lockingDuration
8364

84-
crowdSale.type = 'STAKED_LOCKING_CROWDSALE'
65+
crowdSale.type = 'LOCKING_CROWDSALE'
8566
crowdSale.save()
8667
log.info('[handleStarted] locking crowdsale {}', [crowdSale.id])
8768
}
8869

70+
export function handleStarted(event: StartedEvent): void {
71+
const _plain = new PlainStartedEvent(
72+
event.address,
73+
event.logIndex,
74+
event.transactionLogIndex,
75+
event.logType,
76+
event.block,
77+
event.transaction,
78+
[
79+
event.parameters[0], // uint256 saleId
80+
event.parameters[1], // address issuer
81+
event.parameters[2], // struct Sale
82+
event.parameters[5] // uint16 feeBp
83+
],
84+
event.receipt
85+
)
86+
87+
plainHandleStarted(_plain)
88+
lockingHandleStarted(event)
89+
}
90+
8991
export function handleSettled(event: SettledEvent): void {
9092
GenericCrowdSale.handleSettled(event.params.saleId.toString())
9193
}
@@ -94,29 +96,6 @@ export function handleFailed(event: FailedEvent): void {
9496
GenericCrowdSale.handleFailed(event.params.saleId.toString())
9597
}
9698

97-
export function handleLockingContractCreated(
98-
event: LockingContractCreatedEvent
99-
): void {
100-
let context = new DataSourceContext()
101-
context.setBytes('ipt', event.params.underlyingToken)
102-
context.setBytes('lockingContract', event.params.lockingContract)
103-
TimelockedTokenTemplate.createWithContext(
104-
event.params.lockingContract,
105-
context
106-
)
107-
const _underlyingTokenContract: IERC20Metadata = IERC20Metadata.bind(
108-
event.params.underlyingToken
109-
)
110-
const underlyingErc20Token: ERC20Token = makeERC20Token(
111-
_underlyingTokenContract
112-
)
113-
114-
makeTimelockedToken(
115-
IERC20Metadata.bind(event.params.lockingContract),
116-
underlyingErc20Token
117-
)
118-
}
119-
12099
export function handleBid(event: BidEvent): void {
121100
GenericCrowdSale.handleBid(
122101
new GenericCrowdSale.BidEventParams(
@@ -141,6 +120,29 @@ export function handleClaimed(event: ClaimedEvent): void {
141120
)
142121
}
143122

123+
export function handleLockingContractCreated(
124+
event: LockingContractCreatedEvent
125+
): void {
126+
let context = new DataSourceContext()
127+
context.setBytes('ipt', event.params.underlyingToken)
128+
context.setBytes('lockingContract', event.params.lockingContract)
129+
TimelockedTokenTemplate.createWithContext(
130+
event.params.lockingContract,
131+
context
132+
)
133+
const _underlyingTokenContract: IERC20Metadata = IERC20Metadata.bind(
134+
event.params.underlyingToken
135+
)
136+
const underlyingErc20Token: ERC20Token = makeERC20Token(
137+
_underlyingTokenContract
138+
)
139+
140+
makeTimelockedToken(
141+
IERC20Metadata.bind(event.params.lockingContract),
142+
underlyingErc20Token
143+
)
144+
}
145+
144146
/**
145147
* emitted when the auctioneer pulls / claims bidding tokens after the sale is successfully settled
146148
*/

subgraph/src/stakedLockingCrowdSaleMapping.ts

Lines changed: 47 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import {
2121
} from '../generated/StakedLockingCrowdSale/StakedLockingCrowdSale'
2222

2323
import { Started as PlainStartedEvent } from '../generated/CrowdSale/CrowdSale'
24+
import { Started as LockingStartedEvent } from '../generated/LockingCrowdSale/LockingCrowdSale'
2425

2526
import { handleStarted as plainHandleStarted } from './crowdSaleMapping'
27+
import { lockingHandleStarted, handleLockingContractCreated as lockedHandleLockingContractCreated } from './lockingCrowdSaleMapping'
2628

2729
import * as GenericCrowdSale from './genericCrowdSale'
2830

@@ -31,6 +33,9 @@ import { Contribution, CrowdSale, ERC20Token, IPT } from '../generated/schema'
3133
import { TimelockedToken as TimelockedTokenTemplate } from '../generated/templates'
3234
import { makeERC20Token, makeTimelockedToken } from './common'
3335

36+
/**
37+
* there are contracts that emit the started event without fees
38+
*/
3439
export function handleStartedLegacy(event: LegacyStartedEvent): void {
3540
const parameters = event.parameters
3641
parameters[7] = new ethereum.EventParam(
@@ -60,16 +65,35 @@ export function handleStarted(event: StartedEvent): void {
6065
event.block,
6166
event.transaction,
6267
[
63-
event.parameters[0],
64-
event.parameters[1],
65-
event.parameters[2],
66-
event.parameters[7]
68+
event.parameters[0], // uint256 saleId
69+
event.parameters[1], // address issuer
70+
event.parameters[2], // struct Sale
71+
event.parameters[7] // uint16 feeBp
6772
],
6873
event.receipt
6974
)
7075

7176
plainHandleStarted(_plain)
7277

78+
const _locking = new LockingStartedEvent(
79+
event.address,
80+
event.logIndex,
81+
event.transactionLogIndex,
82+
event.logType,
83+
event.block,
84+
event.transaction,
85+
[
86+
event.parameters[0], // uint256 saleId
87+
event.parameters[1], // address issuer
88+
event.parameters[2], // struct Sale
89+
event.parameters[4], // TimelockedToken
90+
event.parameters[5], // uint256 lockingDuration
91+
event.parameters[7] // uint16 feeBp
92+
],
93+
event.receipt
94+
)
95+
lockingHandleStarted(_locking)
96+
7397
let crowdSale = CrowdSale.load(event.params.saleId.toString())
7498
if (!crowdSale) {
7599
log.error('[Crowdsale] Creation failed for: {}', [
@@ -78,31 +102,6 @@ export function handleStarted(event: StartedEvent): void {
78102
return
79103
}
80104

81-
let ipt = IPT.load(event.params.sale.auctionToken.toHexString())
82-
if (!ipt) {
83-
log.error('[Crowdsale] Ipt not found for id: {}', [
84-
event.params.sale.auctionToken.toHexString()
85-
])
86-
return
87-
}
88-
89-
if (!ipt.lockedToken) {
90-
ipt.lockedToken = event.params.lockingToken
91-
ipt.save()
92-
} else {
93-
let _ipt = changetype<Bytes>(ipt.lockedToken).toHexString()
94-
let _newToken = event.params.lockingToken.toHexString()
95-
if (_ipt != _newToken) {
96-
log.error('the locking token per IPT should be unique {} != {}', [
97-
_ipt,
98-
_newToken
99-
])
100-
}
101-
}
102-
103-
crowdSale.amountStaked = BigInt.fromU32(0)
104-
crowdSale.auctionLockingDuration = event.params.lockingDuration
105-
106105
crowdSale.stakingToken = makeERC20Token(
107106
IERC20Metadata.bind(event.params.staking.stakedToken)
108107
).id
@@ -127,29 +126,6 @@ export function handleFailed(event: FailedEvent): void {
127126
GenericCrowdSale.handleFailed(event.params.saleId.toString())
128127
}
129128

130-
export function handleLockingContractCreated(
131-
event: LockingContractCreatedEvent
132-
): void {
133-
let context = new DataSourceContext()
134-
context.setBytes('ipt', event.params.underlyingToken)
135-
context.setBytes('lockingContract', event.params.lockingContract)
136-
TimelockedTokenTemplate.createWithContext(
137-
event.params.lockingContract,
138-
context
139-
)
140-
const _underlyingTokenContract: IERC20Metadata = IERC20Metadata.bind(
141-
event.params.underlyingToken
142-
)
143-
const underlyingErc20Token: ERC20Token = makeERC20Token(
144-
_underlyingTokenContract
145-
)
146-
147-
makeTimelockedToken(
148-
IERC20Metadata.bind(event.params.lockingContract),
149-
underlyingErc20Token
150-
)
151-
}
152-
153129
export function handleBid(event: BidEvent): void {
154130
GenericCrowdSale.handleBid(
155131
new GenericCrowdSale.BidEventParams(
@@ -161,6 +137,25 @@ export function handleBid(event: BidEvent): void {
161137
)
162138
}
163139

140+
export function handleClaimed(event: ClaimedEvent): void {
141+
GenericCrowdSale.handleClaimed(
142+
new GenericCrowdSale.ClaimedEventParams(
143+
event.params.saleId,
144+
event.params.claimer,
145+
event.params.claimed,
146+
event.params.refunded,
147+
event.block.timestamp,
148+
event.transaction
149+
)
150+
)
151+
}
152+
153+
export function handleLockingContractCreated(
154+
event: LockingContractCreatedEvent
155+
): void {
156+
lockedHandleLockingContractCreated(event)
157+
}
158+
164159
export function handleStaked(event: StakedEvent): void {
165160
let crowdSale = CrowdSale.load(event.params.saleId.toString())
166161

@@ -204,19 +199,6 @@ export function handleStaked(event: StakedEvent): void {
204199
contribution.save()
205200
}
206201

207-
export function handleClaimed(event: ClaimedEvent): void {
208-
GenericCrowdSale.handleClaimed(
209-
new GenericCrowdSale.ClaimedEventParams(
210-
event.params.saleId,
211-
event.params.claimer,
212-
event.params.claimed,
213-
event.params.refunded,
214-
event.block.timestamp,
215-
event.transaction
216-
)
217-
)
218-
}
219-
220202
export function handleClaimedStakes(event: ClaimedStakesEvent): void {
221203
let contributionId =
222204
event.params.saleId.toString() + '-' + event.params.claimer.toHex()

0 commit comments

Comments
 (0)