Contract Functions

Token Exchange

function buy(address ipId) public payable {
        require(checkListed(ipId), "IP is not listed");
        uint256 price = getBuyPrice(ipId);
        (uint256 creatorFee, uint256 protocolFee, uint256 totalFee) = _calcTradingFees(price);
        uint256 priceAfterFee = price + totalFee;
        require(msg.value >= priceAfterFee, "Insufficient payment");
        uint256 assetId = ipIdToAssetId[ipId];
        totalSupply[assetId] += 1;
        poolLiquidity[assetId] += price;
        _mint(msg.sender, assetId, 1, "");
        emit Trade(TradeType.Buy, ipId, assetId, msg.sender, 1, price, creatorFee);
        (bool creatorFeeSent, ) = payable(storyHelper.getIpOwner(ipId)).call{ value: creatorFee }("");
        require(creatorFeeSent, "Failed to send creator fee");
        if (protocolFee > 0) {
            (bool protocolFeeSent, ) = payable(owner()).call{ value: protocolFee }("");
            require(protocolFeeSent, "Failed to send protocol fee");
        }


        if (msg.value > priceAfterFee) {
            (bool refunded, ) = payable(msg.sender).call{ value: msg.value - priceAfterFee }("");
            require(refunded, "Failed to refund excess payment");
        }
    }
function sell(address ipId) public {
        require(checkListed(ipId), "IP is not listed");
        uint256 assetId = ipIdToAssetId[ipId];
        require(balanceOf(msg.sender, assetId) >= 1, "Insufficient balance");
        uint256 supply = totalSupply[assetId];
        require(supply - 1 >= PREMINT, "Supply not allowed below premint amount");
        uint256 price = getSellPrice(ipId);
        (uint256 creatorFee, uint256 protocolFee, uint256 totalFee) = _calcTradingFees(price);
        _burn(msg.sender, assetId, 1);
        totalSupply[assetId] = supply - 1;
        poolLiquidity[assetId] -= price;
        emit Trade(TradeType.Sell, ipId, assetId, msg.sender, 1, price, creatorFee);
        (bool sent, ) = payable(msg.sender).call{ value: price - totalFee }("");
        (bool creatorFeeSent, ) = payable(storyHelper.getIpOwner(ipId)).call{ value: creatorFee }("");
        require(sent && creatorFeeSent, "Failed to send ether");
        if (protocolFee > 0) {
            (bool protocolFeeSent, ) = payable(owner()).call{ value: protocolFee }("");
            require(protocolFeeSent, "Failed to send protocol fee");
        }
    }

Remix

function remix(
        address parentIpId,
        address licenseTemplate,
        uint256 licenseTermsId
    ) public returns (address childIpId) {
        require(checkListed(parentIpId), "IP is not listed");
        require(
            storyHelper.hasIpAttachedLicenseTerm(parentIpId, licenseTemplate, licenseTermsId),
            "IP does not have the license"
        );
        require(!storyHelper.isDisputed(parentIpId), "IP is disputed");
        uint256 parentAssetId = ipIdToAssetId[parentIpId];
        require(balanceOf(msg.sender, parentAssetId) >= PREMINT, "Insufficient balance");
        // Register childIP
        uint256 tokenId = remixingNFT.mint(address(this), storyHelper.getIpUri(parentIpId));
        childIpId = storyHelper.ipAssetRegistry().register(block.chainid, address(remixingNFT), tokenId);
        // Calc minting fee
        (address policy, , uint256 mintingLicenseFee, address currencyToken) = ILicenseTemplate(licenseTemplate)
            .getRoyaltyPolicy(licenseTermsId);
        uint256 configFee = storyHelper.getLicensingConfigFee(parentIpId, childIpId, licenseTemplate, licenseTermsId);
        if (configFee > 0) {
            mintingLicenseFee = configFee;
        }


        if (mintingLicenseFee > 0) {
            IERC20(currencyToken).transferFrom(msg.sender, address(this), mintingLicenseFee);
            IERC20(currencyToken).approve(policy, mintingLicenseFee);
        }
        // Mint derivative
        {
            address[] memory _parents = new address[](1);
            _parents[0] = parentIpId;
            uint256[] memory _lids = new uint256[](1);
            _lids[0] = licenseTermsId;
            storyHelper.licensingModule().registerDerivative(childIpId, _parents, _lids, licenseTemplate, "");
        }
        // Burn parent key
        uint256 sellPrice = getSellPrice(parentIpId);
        _burn(msg.sender, parentAssetId, 1);
        totalSupply[parentAssetId] -= 1;
        poolLiquidity[parentAssetId] -= sellPrice;
        emit Remix(parentIpId, childIpId, msg.sender, licenseTemplate, licenseTermsId, sellPrice, 0);
        uint256 childAssetId = _register(childIpId);
        emit List(childIpId, childAssetId, msg.sender);
        poolLiquidity[childAssetId] += sellPrice;
        remixFloorPrice[childIpId] = sellPrice;
        emit Trade(TradeType.Mint, childIpId, childAssetId, msg.sender, PREMINT, sellPrice, 0);
        remixingNFT.transferFrom(address(this), msg.sender, tokenId);
    }

Price Curve

function curve(uint256 x) public view returns (uint256) {
        int128 supply = ABDKMath64x64.fromUInt(x);
        int128 z = ABDKMath64x64.div(ABDKMath64x64.sub(supply, MEAN), STD);
        int128 a = ABDKMath64x64.abs(z);
        int128 t = ABDKMath64x64.inv(ABDKMath64x64.add(FP_ONE, ABDKMath64x64.mul(a, FP_P)));
        int128 w1 = 0;
        {
            int128 b4_add_t_mul_b5 = ABDKMath64x64.add(FP_MAGIC_NUMBER4, ABDKMath64x64.mul(t, FP_MAGIC_NUMBER5));
            int128 b3_add_t_mul_prev = ABDKMath64x64.add(FP_MAGIC_NUMBER3, ABDKMath64x64.mul(t, b4_add_t_mul_b5));
            int128 b2_add_t_mul_prev = ABDKMath64x64.add(FP_MAGIC_NUMBER2, ABDKMath64x64.mul(t, b3_add_t_mul_prev));
            int128 b1_add_t_mul_prev = ABDKMath64x64.add(FP_MAGIC_NUMBER1, ABDKMath64x64.mul(t, b2_add_t_mul_prev));
            w1 = ABDKMath64x64.mul(t, b1_add_t_mul_prev);
        }
        int128 expasqr = ABDKMath64x64.exp(ABDKMath64x64.neg(ABDKMath64x64.div(ABDKMath64x64.pow(a, 2), FP_TWO)));
        int128 tmp = ABDKMath64x64.mul(ABDKMath64x64.mul(INV_SQRT2PI, expasqr), w1);
        int128 w = ABDKMath64x64.sub(FP_ONE, tmp);
        uint256 price = ABDKMath64x64.mulu(w, BASE_PERCISION);
        if (z < 0) {
            return BASE_PERCISION - price;
        }
        return price;
    }

Last updated