Skip to content

Commit e877da5

Browse files
authored
Fixed issuer offset edge case (#121)
* fixed issuer offset edge case * review update * ran linter * checked in new address
1 parent 04a8a44 commit e877da5

File tree

5 files changed

+76
-22
lines changed

5 files changed

+76
-22
lines changed

spot-contracts/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This repository is a collection of smart contracts that implement the SPOT perpe
55
The official mainnet addresses are:
66

77
- SPOT ERC-20 Token: [0xC1f33e0cf7e40a67375007104B929E49a581bafE](https://etherscan.io/address/0xC1f33e0cf7e40a67375007104B929E49a581bafE)
8-
- Bond issuer: [0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2](https://etherscan.io/address/0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2)
8+
- Bond issuer: [0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66](https://etherscan.io/address/0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66)
99
- Router: [0x38f600e08540178719BF656e6B43FC15A529c393](https://etherscan.io/address/0x38f600e08540178719BF656e6B43FC15A529c393)
1010

1111
## Install

spot-contracts/contracts/BondIssuer.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ contract BondIssuer is IBondIssuer, OwnableUpgradeable {
123123
}
124124

125125
// Set to the timestamp of the most recent issue window start
126-
lastIssueWindowTimestamp = block.timestamp - (block.timestamp % minIssueTimeIntervalSec) + issueWindowOffsetSec;
126+
lastIssueWindowTimestamp =
127+
block.timestamp -
128+
((block.timestamp - issueWindowOffsetSec) % minIssueTimeIntervalSec);
127129

128130
IBondController bond = IBondController(
129131
bondFactory.createBond(collateral, trancheRatios, lastIssueWindowTimestamp + maxMaturityDuration)

spot-contracts/deployments/mainnet.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"ampl": "0xD46bA6D942050d489DBd938a2C909A5d5039A161",
33
"bondFactory": "0x72799FFD1F4CCF92eA2b1eE0CADa16a5461c4d96",
4-
"bondIssuer": "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2",
4+
"bondIssuer": "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66",
55
"spot": "0xC1f33e0cf7e40a67375007104B929E49a581bafE",
66
"proxyAdmin": "0x2978B4103985A6668CE345555b0febdE64Fb092F",
77
"router": "0x38f600e08540178719BF656e6B43FC15A529c393"

spot-contracts/tasks/mainnet.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ yarn hardhat --network mainnet deploy:BondIssuer \
1010
--tranche-ratios "[200,800]"
1111

1212
yarn hardhat --network mainnet deploy:PerpetualTranche \
13-
--bond-issuer-address "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2" \
13+
--bond-issuer-address "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66" \
1414
--collateral-token-address "0xD46bA6D942050d489DBd938a2C909A5d5039A161" \
1515
--name "SPOT" \
1616
--symbol "SPOT" \
@@ -27,7 +27,7 @@ yarn hardhat --network mainnet deploy:Router
2727

2828
########################################################################
2929
## Transfer ownership
30-
yarn hardhat --network mainnet transferOwnership "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2" \
30+
yarn hardhat --network mainnet transferOwnership "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66" \
3131
--new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662"
3232

3333
yarn hardhat --network mainnet transferOwnership "0xFF732cA9EFc95E853FBD71a5c61647cd0C0898a3" \
@@ -42,6 +42,7 @@ yarn hardhat --network mainnet transferOwnership "0xC1f33e0cf7e40a67375007104B92
4242
yarn hardhat --network mainnet transferOwnership "0x2978B4103985A6668CE345555b0febdE64Fb092F" \
4343
--new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662"
4444

45+
4546
########################################################################
4647
## OPS
4748
yarn hardhat --network mainnet ops:info 0xC1f33e0cf7e40a67375007104B929E49a581bafE
@@ -62,6 +63,9 @@ yarn hardhat --network mainnet ops:redeem \
6263
yarn hardhat --network mainnet ops:redeemTranches \
6364
--bond-issuer-address 0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2
6465

66+
yarn hardhat --network mainnet ops:redeemTranches \
67+
--bond-issuer-address 0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66
68+
6569
yarn hardhat --network mainnet ops:trancheAndRollover \
6670
--router-address 0x38f600e08540178719BF656e6B43FC15A529c393 \
6771
--perp-address 0xC1f33e0cf7e40a67375007104B929E49a581bafE \
@@ -70,4 +74,4 @@ yarn hardhat --network mainnet ops:trancheAndRollover \
7074
########################################################################
7175
## upgrade
7276

73-
yarn hardhat --network mainnet prepare_upgrade:perp:mainnet 0xC1f33e0cf7e40a67375007104B929E49a581bafE
77+
yarn hardhat --network mainnet prepare_upgrade:perp:mainnet 0xC1f33e0cf7e40a67375007104B929E49a581bafE

spot-contracts/test/BondIssuer.ts

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { expect } from "chai";
2-
import { ethers } from "hardhat";
2+
import { ethers, network } from "hardhat";
33
import { Contract, Signer } from "ethers";
44

55
import { TimeHelpers, setupBondFactory } from "./helpers";
66

7+
const START_TIME = 2499998400;
8+
const mockTime = (x: number) => START_TIME + x;
9+
710
let bondFactory: Contract, token: Contract, issuer: Contract, deployer: Signer, otherUser: Signer;
811
describe("BondIssuer", function () {
912
beforeEach(async function () {
@@ -16,15 +19,20 @@ describe("BondIssuer", function () {
1619
await token.init("Test token", "TEST");
1720
const BondIssuer = await ethers.getContractFactory("BondIssuer");
1821
issuer = await BondIssuer.deploy(bondFactory.address, token.address);
19-
await issuer.init(86400, [200, 300, 500], 3600, 120);
22+
await issuer.init(86400, [200, 300, 500], 3600, 900);
23+
await TimeHelpers.setNextBlockTimestamp(mockTime(0));
24+
});
25+
26+
afterEach(async function () {
27+
await network.provider.send("hardhat_reset");
2028
});
2129

2230
describe("#setup", function () {
2331
it("should set storage parameters", async function () {
2432
expect(await issuer.owner()).to.eq(await deployer.getAddress());
2533
expect(await issuer.bondFactory()).to.eq(bondFactory.address);
2634
expect(await issuer.minIssueTimeIntervalSec()).to.eq(3600);
27-
expect(await issuer.issueWindowOffsetSec()).to.eq(120);
35+
expect(await issuer.issueWindowOffsetSec()).to.eq(900);
2836
expect(await issuer.maxMaturityDuration()).to.eq(86400);
2937
expect(await issuer.collateral()).to.eq(token.address);
3038
expect(await issuer.trancheRatios(0)).to.eq(200);
@@ -94,7 +102,7 @@ describe("BondIssuer", function () {
94102
describe("#issue", function () {
95103
describe("when sufficient time has passed", function () {
96104
it("should issue a new bond", async function () {
97-
await TimeHelpers.setNextBlockTimestamp(2499998400);
105+
await TimeHelpers.setNextBlockTimestamp(mockTime(901));
98106
const tx = await issuer.issue();
99107
const txR = await tx.wait();
100108
const bondIssuedEvent = txR.events[txR.events.length - 1];
@@ -103,34 +111,74 @@ describe("BondIssuer", function () {
103111
expect(tx).to.emit(issuer, "BondIssued");
104112
expect(await issuer.isInstance(bond)).to.eq(true);
105113
expect(await issuer.callStatic.getLatestBond()).to.eq(bond);
106-
expect(await issuer.lastIssueWindowTimestamp()).to.eq(2499998520);
114+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
107115

108116
expect(await issuer.issuedCount()).to.eq(1);
109117
expect(await issuer.issuedBondAt(0)).to.eq(bond);
110118
await expect(issuer.issuedBondAt(1)).to.be.reverted;
111119

112-
await TimeHelpers.setNextBlockTimestamp(2500002120);
120+
await TimeHelpers.setNextBlockTimestamp(mockTime(4495));
121+
await expect(issuer.issue()).not.to.emit(issuer, "BondIssued");
122+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
123+
124+
await TimeHelpers.setNextBlockTimestamp(mockTime(4501));
113125
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
114-
expect(await issuer.lastIssueWindowTimestamp()).to.eq(2500002120);
126+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
115127

116128
expect(await issuer.issuedCount()).to.eq(2);
117129
await expect(issuer.issuedBondAt(1)).to.not.be.reverted;
130+
131+
await TimeHelpers.setNextBlockTimestamp(mockTime(4505));
132+
await expect(issuer.issue()).not.to.emit(issuer, "BondIssued");
133+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
118134
});
119135
});
120136

121-
describe("when sufficient time has not passed", function () {
122-
it("should not issue a new bond", async function () {
123-
await TimeHelpers.setNextBlockTimestamp(2500005720);
137+
describe("for various elapsed times lastIssueWindowTimestamp", function () {
138+
beforeEach(async function () {
139+
expect(await issuer.lastIssueWindowTimestamp()).to.eq("0");
140+
});
141+
142+
it("should should snap down", async function () {
143+
await TimeHelpers.setNextBlockTimestamp(mockTime(3500));
124144
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
125-
expect(await issuer.issuedCount()).to.eq(1);
145+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
146+
});
126147

127-
await TimeHelpers.setNextBlockTimestamp(2500009310);
128-
await expect(issuer.issue()).not.to.emit(issuer, "BondIssued");
129-
expect(await issuer.issuedCount()).to.eq(1);
148+
it("should should snap down", async function () {
149+
await TimeHelpers.setNextBlockTimestamp(mockTime(3595));
150+
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
151+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
152+
});
130153

131-
await TimeHelpers.setNextBlockTimestamp(2500009320);
154+
it("should should snap down", async function () {
155+
await TimeHelpers.setNextBlockTimestamp(mockTime(3600));
132156
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
133-
expect(await issuer.issuedCount()).to.eq(2);
157+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
158+
});
159+
160+
it("should should snap down", async function () {
161+
await TimeHelpers.setNextBlockTimestamp(mockTime(4495));
162+
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
163+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
164+
});
165+
166+
it("should should snap down", async function () {
167+
await TimeHelpers.setNextBlockTimestamp(mockTime(4500));
168+
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
169+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
170+
});
171+
172+
it("should should snap down", async function () {
173+
await TimeHelpers.setNextBlockTimestamp(mockTime(4501));
174+
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
175+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
176+
});
177+
178+
it("should should snap down", async function () {
179+
await TimeHelpers.setNextBlockTimestamp(mockTime(4600));
180+
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
181+
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
134182
});
135183
});
136184
});

0 commit comments

Comments
 (0)