Skip to content

Commit

Permalink
Fixed issuer offset edge case (#121)
Browse files Browse the repository at this point in the history
* fixed issuer offset edge case

* review update

* ran linter

* checked in new address
  • Loading branch information
aalavandhan authored Dec 8, 2022
1 parent 04a8a44 commit e877da5
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 22 deletions.
2 changes: 1 addition & 1 deletion spot-contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This repository is a collection of smart contracts that implement the SPOT perpe
The official mainnet addresses are:

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

## Install
Expand Down
4 changes: 3 additions & 1 deletion spot-contracts/contracts/BondIssuer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ contract BondIssuer is IBondIssuer, OwnableUpgradeable {
}

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

IBondController bond = IBondController(
bondFactory.createBond(collateral, trancheRatios, lastIssueWindowTimestamp + maxMaturityDuration)
Expand Down
2 changes: 1 addition & 1 deletion spot-contracts/deployments/mainnet.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"ampl": "0xD46bA6D942050d489DBd938a2C909A5d5039A161",
"bondFactory": "0x72799FFD1F4CCF92eA2b1eE0CADa16a5461c4d96",
"bondIssuer": "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2",
"bondIssuer": "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66",
"spot": "0xC1f33e0cf7e40a67375007104B929E49a581bafE",
"proxyAdmin": "0x2978B4103985A6668CE345555b0febdE64Fb092F",
"router": "0x38f600e08540178719BF656e6B43FC15A529c393"
Expand Down
10 changes: 7 additions & 3 deletions spot-contracts/tasks/mainnet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ yarn hardhat --network mainnet deploy:BondIssuer \
--tranche-ratios "[200,800]"

yarn hardhat --network mainnet deploy:PerpetualTranche \
--bond-issuer-address "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2" \
--bond-issuer-address "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66" \
--collateral-token-address "0xD46bA6D942050d489DBd938a2C909A5d5039A161" \
--name "SPOT" \
--symbol "SPOT" \
Expand All @@ -27,7 +27,7 @@ yarn hardhat --network mainnet deploy:Router

########################################################################
## Transfer ownership
yarn hardhat --network mainnet transferOwnership "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2" \
yarn hardhat --network mainnet transferOwnership "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66" \
--new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662"

yarn hardhat --network mainnet transferOwnership "0xFF732cA9EFc95E853FBD71a5c61647cd0C0898a3" \
Expand All @@ -42,6 +42,7 @@ yarn hardhat --network mainnet transferOwnership "0xC1f33e0cf7e40a67375007104B92
yarn hardhat --network mainnet transferOwnership "0x2978B4103985A6668CE345555b0febdE64Fb092F" \
--new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662"


########################################################################
## OPS
yarn hardhat --network mainnet ops:info 0xC1f33e0cf7e40a67375007104B929E49a581bafE
Expand All @@ -62,6 +63,9 @@ yarn hardhat --network mainnet ops:redeem \
yarn hardhat --network mainnet ops:redeemTranches \
--bond-issuer-address 0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2

yarn hardhat --network mainnet ops:redeemTranches \
--bond-issuer-address 0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66

yarn hardhat --network mainnet ops:trancheAndRollover \
--router-address 0x38f600e08540178719BF656e6B43FC15A529c393 \
--perp-address 0xC1f33e0cf7e40a67375007104B929E49a581bafE \
Expand All @@ -70,4 +74,4 @@ yarn hardhat --network mainnet ops:trancheAndRollover \
########################################################################
## upgrade

yarn hardhat --network mainnet prepare_upgrade:perp:mainnet 0xC1f33e0cf7e40a67375007104B929E49a581bafE
yarn hardhat --network mainnet prepare_upgrade:perp:mainnet 0xC1f33e0cf7e40a67375007104B929E49a581bafE
80 changes: 64 additions & 16 deletions spot-contracts/test/BondIssuer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import { ethers, network } from "hardhat";
import { Contract, Signer } from "ethers";

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

const START_TIME = 2499998400;
const mockTime = (x: number) => START_TIME + x;

let bondFactory: Contract, token: Contract, issuer: Contract, deployer: Signer, otherUser: Signer;
describe("BondIssuer", function () {
beforeEach(async function () {
Expand All @@ -16,15 +19,20 @@ describe("BondIssuer", function () {
await token.init("Test token", "TEST");
const BondIssuer = await ethers.getContractFactory("BondIssuer");
issuer = await BondIssuer.deploy(bondFactory.address, token.address);
await issuer.init(86400, [200, 300, 500], 3600, 120);
await issuer.init(86400, [200, 300, 500], 3600, 900);
await TimeHelpers.setNextBlockTimestamp(mockTime(0));
});

afterEach(async function () {
await network.provider.send("hardhat_reset");
});

describe("#setup", function () {
it("should set storage parameters", async function () {
expect(await issuer.owner()).to.eq(await deployer.getAddress());
expect(await issuer.bondFactory()).to.eq(bondFactory.address);
expect(await issuer.minIssueTimeIntervalSec()).to.eq(3600);
expect(await issuer.issueWindowOffsetSec()).to.eq(120);
expect(await issuer.issueWindowOffsetSec()).to.eq(900);
expect(await issuer.maxMaturityDuration()).to.eq(86400);
expect(await issuer.collateral()).to.eq(token.address);
expect(await issuer.trancheRatios(0)).to.eq(200);
Expand Down Expand Up @@ -94,7 +102,7 @@ describe("BondIssuer", function () {
describe("#issue", function () {
describe("when sufficient time has passed", function () {
it("should issue a new bond", async function () {
await TimeHelpers.setNextBlockTimestamp(2499998400);
await TimeHelpers.setNextBlockTimestamp(mockTime(901));
const tx = await issuer.issue();
const txR = await tx.wait();
const bondIssuedEvent = txR.events[txR.events.length - 1];
Expand All @@ -103,34 +111,74 @@ describe("BondIssuer", function () {
expect(tx).to.emit(issuer, "BondIssued");
expect(await issuer.isInstance(bond)).to.eq(true);
expect(await issuer.callStatic.getLatestBond()).to.eq(bond);
expect(await issuer.lastIssueWindowTimestamp()).to.eq(2499998520);
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));

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

await TimeHelpers.setNextBlockTimestamp(2500002120);
await TimeHelpers.setNextBlockTimestamp(mockTime(4495));
await expect(issuer.issue()).not.to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));

await TimeHelpers.setNextBlockTimestamp(mockTime(4501));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(2500002120);
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));

expect(await issuer.issuedCount()).to.eq(2);
await expect(issuer.issuedBondAt(1)).to.not.be.reverted;

await TimeHelpers.setNextBlockTimestamp(mockTime(4505));
await expect(issuer.issue()).not.to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
});
});

describe("when sufficient time has not passed", function () {
it("should not issue a new bond", async function () {
await TimeHelpers.setNextBlockTimestamp(2500005720);
describe("for various elapsed times lastIssueWindowTimestamp", function () {
beforeEach(async function () {
expect(await issuer.lastIssueWindowTimestamp()).to.eq("0");
});

it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(3500));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.issuedCount()).to.eq(1);
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
});

await TimeHelpers.setNextBlockTimestamp(2500009310);
await expect(issuer.issue()).not.to.emit(issuer, "BondIssued");
expect(await issuer.issuedCount()).to.eq(1);
it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(3595));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
});

await TimeHelpers.setNextBlockTimestamp(2500009320);
it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(3600));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.issuedCount()).to.eq(2);
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
});

it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(4495));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(900));
});

it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(4500));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
});

it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(4501));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
});

it("should should snap down", async function () {
await TimeHelpers.setNextBlockTimestamp(mockTime(4600));
await expect(issuer.issue()).to.emit(issuer, "BondIssued");
expect(await issuer.lastIssueWindowTimestamp()).to.eq(mockTime(4500));
});
});
});
Expand Down

0 comments on commit e877da5

Please sign in to comment.