fix receiveApproval

This commit is contained in:
Ricardo Guilherme Schmidt 2019-02-14 15:09:26 -02:00
parent 7e863d9eef
commit 0bb455a18a
No known key found for this signature in database
GPG Key ID: BFB3F5C8ED618A94
4 changed files with 135 additions and 15 deletions

View File

@ -1,4 +1,4 @@
pragma solidity >=0.5.3 <0.6.0;
pragma solidity >=0.5.0 <0.6.0;
import "../../token/NonfungibleToken.sol";
import "../../token/ERC20Token.sol";
@ -203,14 +203,15 @@ contract StickerMarket is Controlled, NonfungibleToken, ApproveAndCallFallBack {
{
require(_token == address(snt), "Bad token");
require(_token == address(msg.sender), "Bad call");
if(msg.sig == bytes4(keccak256("buyToken(uint256,address)"))){
require(_data.length == 56, "Bad data length");
(uint256 packId, address owner) = abi.decode(msg.data, (uint256, address));
bytes4 sig = abiDecodeSig(_data);
bytes memory cdata = slice(_data,4,_data.length-4);
if(sig == bytes4(keccak256("buyToken(uint256,address)"))){
require(cdata.length == 64, "Bad data length");
(uint256 packId, address owner) = abi.decode(cdata, (uint256, address));
buy(_from, packId, owner);
} else if(msg.sig == bytes4(keccak256("registerPack(uint256,uint256,bytes4,address,bytes)"))) {
require(_data.length > 60, "Bad data length");
(uint256 _price, uint256 _donate, bytes4[] memory _category, address _owner, bytes memory _contenthash) = abi.decode(msg.data, (uint256,uint256,bytes4[],address,bytes));
} else if(sig == bytes4(keccak256("registerPack(uint256,uint256,bytes4[],address,bytes)"))) {
require(cdata.length >= 156, "Bad data length");
(uint256 _price, uint256 _donate, bytes4[] memory _category, address _owner, bytes memory _contenthash) = abi.decode(cdata, (uint256,uint256,bytes4[],address,bytes));
register(_from, _category, _owner, _price, _donate, _contenthash);
} else {
revert("Bad call");
@ -522,4 +523,69 @@ contract StickerMarket is Controlled, NonfungibleToken, ApproveAndCallFallBack {
pack = packs[tokenPackId[_tokenId]];
}
function abiDecodeSig(bytes memory _data) private pure returns(bytes4 sig){
assembly {
sig := mload(add(_data, add(0x20, 0)))
}
}
function slice(bytes memory _bytes, uint _start, uint _length) private pure returns (bytes memory) {
require(_bytes.length >= (_start + _length));
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
}

View File

@ -621,13 +621,13 @@ contract MiniMeToken is Controlled {
////////////////
// Events
////////////////
event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
event Transfer(address indexed _from, address indexed _to, uint256 _amount);
event NewCloneToken(address indexed _cloneToken, uint snapshotBlock);
event ClaimedTokens(address indexed token, address indexed controller, uint amount);
event Transfer(address indexed from, address indexed to, uint256 amount);
event NewCloneToken(address indexed cloneToken, uint snapshotBlock);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _amount
address indexed owner,
address indexed spender,
uint256 amount
);
}

View File

@ -10,7 +10,7 @@
"config": "config/",
"versions": {
"web3": "1.0.0-beta",
"solc": "0.5.3",
"solc": "0.5.4",
"ipfs-api": "17.2.4",
"p-iteration": "1.1.7"
},

View File

@ -170,6 +170,60 @@ contract("StickerMarket", function() {
}
});
it("should mint packs with approveAndCall", async function() {
let burnRate = 10;
await StickerMarket.methods.setBurnRate(burnRate).send();
let packBuyer = accounts[2];
for(let i = 0; i < registeredPacks.length; i++){
await TestStatusNetwork.methods.mint(registeredPacks[i].data.price).send({from: packBuyer });
const buyCall = StickerMarket.methods.buyToken(registeredPacks[i].id, packBuyer).encodeABI();
let buy = await MiniMeToken.methods.approveAndCall(StickerMarket.address, registeredPacks[i].data.price, buyCall).send({from: packBuyer });
let tokenId;
let toArtist = 0;
let donated = 0;
let burned = 0;
let burnAddress =(await MiniMeToken.methods.controller().call());
for(let j = 0; j < buy.events.Transfer.length; j++) {
if(buy.events.Transfer[j].address == MiniMeToken.address){
if(buy.events.Transfer[j].returnValues[1] == StickerMarket.address){
donated = parseInt(buy.events.Transfer[j].raw.data, 16).toString(10)
}else if(buy.events.Transfer[j].returnValues[1] == registeredPacks[i].data.owner){
toArtist = parseInt(buy.events.Transfer[j].raw.data, 16).toString(10)
}else if(buy.events.Transfer[j].returnValues[1] == burnAddress){
burned = parseInt(buy.events.Transfer[j].raw.data, 16).toString(10)
}
}else if(buy.events.Transfer[j].address == StickerMarket.address){
tokenId = parseInt(buy.events.Transfer[j].raw.data, 16).toString(10);
}
}
assert.equal(registeredPacks[i].data.price, (+toArtist + +donated + +burned), "Bad payment")
assert.equal(burned, (registeredPacks[i].data.price * burnRate) / 10000, "Bad burn")
assert.equal(donated, ((+registeredPacks[i].data.price - burned) * registeredPacks[i].data.donate)/10000, "Bad donate")
assert.equal(toArtist, registeredPacks[i].data.price - (+donated + +burned), "Bad profit")
assert.equal(await StickerMarket.methods.ownerOf(tokenId).call(), packBuyer, "Bad owner")
}
});
it("should register pack with approveAndCall", async function() {
let registerFee = "1000000000000000000";
await StickerMarket.methods.setRegisterFee(registerFee).send();
await TestStatusNetwork.methods.mint(registerFee).send();
let pack = testPacks[0];
let regCall = await StickerMarket.methods.registerPack(pack.price, pack.donate, pack.category, pack.owner, pack.contentHash).encodeABI();
let packId = await StickerMarket.methods.packCount().call();
let reg = await MiniMeToken.methods.approveAndCall(StickerMarket.address, registerFee, regCall).send();
for(let j = 0; j < pack.category.length; j++) {
assert.notEqual((await StickerMarket.methods.getAvailablePacks(pack.category[j]).call()).indexOf(packId), -1);
}
await StickerMarket.methods.purgePack(packId, 0).send();
await StickerMarket.methods.setRegisterFee("0").send();
});
it("should purge packs", async function() {
var i = 0;
await StickerMarket.methods.purgePack(registeredPacks[i].id, 0).send();