Browse Source

implement tests for ownership

dev/signature-instant-buy
igor 2 years ago
parent
commit
b4e9c137b3
  1. 3
      .gitmodules
  2. 1
      contracts/dns-contract
  3. 37
      contracts/main.ts
  4. 76
      package-lock.json
  5. 2
      package.json
  6. 51
      test/ownership.spec.ts

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "contracts/dns-contract"]
path = contracts/dns-contract
url = https://github.com/ton-blockchain/dns-contract.git

1
contracts/dns-contract

@ -0,0 +1 @@
Subproject commit d08131031fb659d2826cccc417ddd9b98476f814

37
contracts/main.ts

@ -1,32 +1,57 @@
import BN from "bn.js"; import BN from "bn.js";
import { Cell, beginCell, Address } from "ton"; import { Cell, beginCell, Address } from "ton";
import { C7Config, SmartContract } from "ton-contract-executor";
import {encodeOffChainContent, makeSnakeCell} from "./utils"; import {encodeOffChainContent, makeSnakeCell} from "./utils";
// encode contract storage according to save_data() contract method // encode contract storage according to save_data() contract method
// collection_content:^Cell
// nft_item_code:^Cell // nft_item_code:^Cell
// uint256 index // uint256 index
// MsgAddressInt collection_address // MsgAddressInt collection_address
// MsgAddressInt owner_address // MsgAddressInt owner_address
// collection_content:^Cell
// cell domain - e.g contains "alice" (without ending \0) for "alice.ton" domain // cell domain - e.g contains "alice" (without ending \0) for "alice.ton" domain
// cell auction - auction info // cell auction - auction info
// int last_fill_up_time // int64 last_fill_up_time
export function data(params: { ownerAddress: Address; collectionAddress: Address, code: Cell, domain: String }): Cell { export function data(params: { ownerAddress: Address; collectionAddress: Address, code: Cell, domain: String }): Cell {
return beginCell() return beginCell()
.storeRef(encodeOffChainContent("https://agorata.io/collection.json")) // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md
// For code: https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-auction/build.sh // For code: https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-auction/build.sh
.storeRef(params.code) .storeRef(params.code)
.storeUint8(0) .storeUint(0, 256)
.storeAddress(params.collectionAddress) .storeAddress(params.collectionAddress)
.storeAddress(params.ownerAddress) .storeAddress(params.ownerAddress)
.storeRef(encodeOffChainContent("https://agorata.io/collection.json")) // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md
.storeRef(makeSnakeCell(Buffer.from(params.domain))) .storeRef(makeSnakeCell(Buffer.from(params.domain)))
.storeRef(beginCell().endCell()) .storeDict(null)
.storeUint(0, 64).endCell(); .storeUint(0, 64).endCell();
} }
export function auctionWithWinner(winnerAddress: Address) {
return beginCell().storeAddress(winnerAddress).storeCoins(0).storeUint(0, 64)
}
export function setContractBalance(contract: SmartContract, balance: number) {
contract.setC7Config({balance: balance});
}
export function TON(): number { return 1000000000; }
// message encoders for all ops (see contracts/imports/constants.fc for consts) // message encoders for all ops (see contracts/imports/constants.fc for consts)
export function transferOwnership(params: { newOwnerAddress: Address }): Cell { export function transferOwnership(params: { newOwnerAddress: Address }): Cell {
return beginCell().storeUint(0x2da38aaf, 32).storeUint(0, 64).storeAddress(params.newOwnerAddress).endCell(); return beginCell().storeUint(0x5fcc3d14, 32).storeUint(0, 64).storeAddress(params.newOwnerAddress).storeAddress(null).storeInt(0, 1).storeCoins(1 * TON()).endCell();
}
export function currentState(contract: SmartContract) {
let reader = contract.dataCell.beginParse();
return {
nft_item_code: reader.readRef(),
index: reader.readUint(256),
collectionAddress: reader.readAddress(),
ownerAddress: reader.readAddress(),
collectionContent: reader.readRef(),
domain: reader.readRef(),
// auction: reader.readCell(), – TODO: still havent's figured out to load auction here
// lastFillUpTime: reader.readInt(64)
}
} }

76
package-lock.json generated

@ -26,7 +26,7 @@
"mocha": "^9.1.3", "mocha": "^9.1.3",
"prando": "^6.0.1", "prando": "^6.0.1",
"prettier": "^2.6.2", "prettier": "^2.6.2",
"ton": "^12.1.3", "ton": "9.9.0",
"ton-contract-executor": "^0.4.8", "ton-contract-executor": "^0.4.8",
"ton-crypto": "^3.1.0", "ton-crypto": "^3.1.0",
"ts-node": "^10.4.0", "ts-node": "^10.4.0",
@ -1715,9 +1715,9 @@
} }
}, },
"node_modules/ton": { "node_modules/ton": {
"version": "12.1.3", "version": "9.9.0",
"resolved": "https://registry.npmjs.org/ton/-/ton-12.1.3.tgz", "resolved": "https://registry.npmjs.org/ton/-/ton-9.9.0.tgz",
"integrity": "sha512-ZkXyr2UkYEQfCX5QKY9xQfzLyM4MDZE+Lz7RICr74wS3fwk5lkJ1/KrQZqb2/DwtoBonEaiNjm6x+r86Q8peFA==", "integrity": "sha512-6t+/5b/6DbQH58ywJoc96CN1txcxXjZfYXk/vDeJClqfFR5Z9QikfoPGjLPHTkpLo8jALGPrcKnZDYIwU6biew==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"axios": "^0.25.0", "axios": "^0.25.0",
@ -1765,36 +1765,6 @@
"ton-compiler": "^0.9.0" "ton-compiler": "^0.9.0"
} }
}, },
"node_modules/ton-contract-executor/node_modules/ton": {
"version": "9.9.0",
"resolved": "https://registry.npmjs.org/ton/-/ton-9.9.0.tgz",
"integrity": "sha512-6t+/5b/6DbQH58ywJoc96CN1txcxXjZfYXk/vDeJClqfFR5Z9QikfoPGjLPHTkpLo8jALGPrcKnZDYIwU6biew==",
"dev": true,
"dependencies": {
"axios": "^0.25.0",
"bn.js": "5.2.0",
"dataloader": "^2.0.0",
"ethjs-unit": "0.1.6",
"fp-ts": "^2.11.1",
"io-ts": "^2.2.16",
"io-ts-reporters": "^2.0.0",
"symbol.inspect": "1.0.1",
"teslabot": "^1.3.0",
"ton-crypto": "2.1.0",
"tweetnacl": "1.0.3"
}
},
"node_modules/ton-contract-executor/node_modules/ton-crypto": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ton-crypto/-/ton-crypto-2.1.0.tgz",
"integrity": "sha512-PZnmCOShfgq9tCRM8E7hG8nCkpkOyZvDLPXmZN92ZEBrfTT0NKKf0imndkxG5DkgWMjc6IKfgpnEaJDH9qN6ZQ==",
"dev": true,
"dependencies": {
"jssha": "3.2.0",
"ton-crypto-primitives": "2.0.0",
"tweetnacl": "1.0.3"
}
},
"node_modules/ton-crypto": { "node_modules/ton-crypto": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/ton-crypto/-/ton-crypto-3.1.0.tgz", "resolved": "https://registry.npmjs.org/ton-crypto/-/ton-crypto-3.1.0.tgz",
@ -3191,9 +3161,9 @@
} }
}, },
"ton": { "ton": {
"version": "12.1.3", "version": "9.9.0",
"resolved": "https://registry.npmjs.org/ton/-/ton-12.1.3.tgz", "resolved": "https://registry.npmjs.org/ton/-/ton-9.9.0.tgz",
"integrity": "sha512-ZkXyr2UkYEQfCX5QKY9xQfzLyM4MDZE+Lz7RICr74wS3fwk5lkJ1/KrQZqb2/DwtoBonEaiNjm6x+r86Q8peFA==", "integrity": "sha512-6t+/5b/6DbQH58ywJoc96CN1txcxXjZfYXk/vDeJClqfFR5Z9QikfoPGjLPHTkpLo8jALGPrcKnZDYIwU6biew==",
"dev": true, "dev": true,
"requires": { "requires": {
"axios": "^0.25.0", "axios": "^0.25.0",
@ -3249,38 +3219,6 @@
"bn.js": "^5.2.0", "bn.js": "^5.2.0",
"ton": "^9.6.3", "ton": "^9.6.3",
"ton-compiler": "^0.9.0" "ton-compiler": "^0.9.0"
},
"dependencies": {
"ton": {
"version": "9.9.0",
"resolved": "https://registry.npmjs.org/ton/-/ton-9.9.0.tgz",
"integrity": "sha512-6t+/5b/6DbQH58ywJoc96CN1txcxXjZfYXk/vDeJClqfFR5Z9QikfoPGjLPHTkpLo8jALGPrcKnZDYIwU6biew==",
"dev": true,
"requires": {
"axios": "^0.25.0",
"bn.js": "5.2.0",
"dataloader": "^2.0.0",
"ethjs-unit": "0.1.6",
"fp-ts": "^2.11.1",
"io-ts": "^2.2.16",
"io-ts-reporters": "^2.0.0",
"symbol.inspect": "1.0.1",
"teslabot": "^1.3.0",
"ton-crypto": "2.1.0",
"tweetnacl": "1.0.3"
}
},
"ton-crypto": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ton-crypto/-/ton-crypto-2.1.0.tgz",
"integrity": "sha512-PZnmCOShfgq9tCRM8E7hG8nCkpkOyZvDLPXmZN92ZEBrfTT0NKKf0imndkxG5DkgWMjc6IKfgpnEaJDH9qN6ZQ==",
"dev": true,
"requires": {
"jssha": "3.2.0",
"ton-crypto-primitives": "2.0.0",
"tweetnacl": "1.0.3"
}
}
} }
}, },
"ton-crypto": { "ton-crypto": {

2
package.json

@ -26,7 +26,7 @@
"mocha": "^9.1.3", "mocha": "^9.1.3",
"prando": "^6.0.1", "prando": "^6.0.1",
"prettier": "^2.6.2", "prettier": "^2.6.2",
"ton": "^12.1.3", "ton": "9.9.0",
"ton-contract-executor": "^0.4.8", "ton-contract-executor": "^0.4.8",
"ton-crypto": "^3.1.0", "ton-crypto": "^3.1.0",
"ts-node": "^10.4.0", "ts-node": "^10.4.0",

51
test/ownership.spec.ts

@ -1,9 +1,9 @@
import chai, { expect } from "chai"; import chai, { assert, expect } from "chai";
import chaiBN from "chai-bn"; import chaiBN from "chai-bn";
import BN from "bn.js"; import BN from "bn.js";
chai.use(chaiBN(BN)); chai.use(chaiBN(BN));
import { Cell, Slice } from "ton"; import { Builder, Cell, Slice } from "ton";
import { SmartContract } from "ton-contract-executor"; import { SmartContract } from "ton-contract-executor";
import * as main from "../contracts/main"; import * as main from "../contracts/main";
import { internalMessage, randomAddress } from "./helpers"; import { internalMessage, randomAddress } from "./helpers";
@ -12,19 +12,62 @@ import { hex } from "../build/main.compiled.json";
describe("Transfer ownership tests", () => { describe("Transfer ownership tests", () => {
let contract: SmartContract; let contract: SmartContract;
let debug: boolean = false;
beforeEach(async () => { beforeEach(async () => {
contract = await SmartContract.fromCell( contract = await SmartContract.fromCell(
Cell.fromBoc(hex)[0], // code cell from build output Cell.fromBoc(hex)[0],
main.data({ main.data({
ownerAddress: randomAddress("owner"), ownerAddress: randomAddress("owner"),
code: Cell.fromBoc(hex)[0], code: Cell.fromBoc(hex)[0],
collectionAddress: randomAddress("collection"), collectionAddress: randomAddress("collection"),
domain: "alice", domain: "alice",
}) }),
{ debug: debug }
); );
}); });
it("transfers ownership to self with no error", async () => {
main.setContractBalance(contract, 10 * main.TON());
let ownerAddr = randomAddress("owner");
const sendToSelfMessage = internalMessage({
from: ownerAddr,
body: main.transferOwnership({ newOwnerAddress: ownerAddr }),
});
const res = await contract.sendInternalMessage(sendToSelfMessage);
expect(res.type).to.equal("success");
expect(res.exit_code).to.equal(0);
assert(main.currentState(contract).ownerAddress?.equals(ownerAddr), "owner address changed after transferring to self");
});
it("should allow the owner to transfer ownership", async () => {
main.setContractBalance(contract, 10 * main.TON());
let ownerAddr = randomAddress("owner");
let receiverAddr = randomAddress("receiver");
const sendToSelfMessage = internalMessage({
from: ownerAddr,
body: main.transferOwnership({ newOwnerAddress: receiverAddr }),
});
const res = await contract.sendInternalMessage(sendToSelfMessage);
expect(res.type).to.equal("success");
expect(res.exit_code).to.equal(0);
assert(main.currentState(contract).ownerAddress?.equals(receiverAddr));
});
it("should prevent others from changing owners", async () => {
main.setContractBalance(contract, 10 * main.TON());
let ownerAddr = randomAddress("owner");
let otherAddr = randomAddress("receiver");
const sendToSelfMessage = internalMessage({
from: otherAddr,
body: main.transferOwnership({ newOwnerAddress: otherAddr }),
});
const res = await contract.sendInternalMessage(sendToSelfMessage);
expect(res.type).to.equal("failed");
expect(res.exit_code).to.equal(401);
assert(main.currentState(contract).ownerAddress?.equals(ownerAddr));
});
// it("should allow the owner to change owners", async () => { // it("should allow the owner to change owners", async () => {
// const send = await contract.sendInternalMessage( // const send = await contract.sendInternalMessage(
// internalMessage({ // internalMessage({

Loading…
Cancel
Save