Skip to content

Commit

Permalink
First pass at updating from PA1D to Royalty
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderattar committed Nov 22, 2022
1 parent 1d0bfe4 commit b2e9584
Show file tree
Hide file tree
Showing 29 changed files with 407 additions and 399 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ Holographer exists at the core of all _Holographed_ smart contracts, which is ap

Enforcer enables and ensures complete standards, compliance, and operability for a given standard type. HolographERC20 and HolographERC721 are perfect examples of such Enforcers. Enforcers store and manage all data within themselves to ensure security, compliance, integrity, and enforcement of all protocols. Communication is established with custom contracts via specific event hooks. The storage/data layer is isolated privately and not directly accessible by custom contracts.

#### PA1D.sol
#### Royalty.sol

PA1D is an on-chain royalties contract for non-fungible token types. It supports a universal module that understands and speaks all of the different royalty standards on the blockchain. PA1D is built to be extendable and can have new royalty standards implemented as they are created and agreed upon.
Royalty is an on-chain royalties contract for non-fungible token types. It supports a universal module that understands and speaks all of the different royalty standards on the blockchain. Royalty is built to be extendable and can have new royalty standards implemented as they are created and agreed upon.

#### Interfaces.sol

Expand Down
2 changes: 1 addition & 1 deletion contracts/HolographInterfaces.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ import "./interface/ERC721Enumerable.sol";
import "./interface/ERC721Metadata.sol";
import "./interface/ERC721TokenReceiver.sol";
import "./interface/InitializableInterface.sol";
import "./interface/PA1DInterface.sol";
import "./interface/RoyaltyInterface.sol";

import "./library/Base64.sol";
import "./library/Strings.sol";
Expand Down
5 changes: 1 addition & 4 deletions contracts/HolographRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,7 @@ contract HolographRegistry is Admin, Initializable, HolographRegistryInterface {
assembly {
contractType := extcodehash(contractAddress)
}
require(
(contractType != 0x0 && contractType != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470),
"HOLOGRAPH: empty contract"
);
require((contractType != 0x0 && contractType != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470), "HOLOGRAPH: empty contract");
require(_contractTypeAddresses[contractType] == address(0), "HOLOGRAPH: contract already set");
require(!_reservedTypes[contractType], "HOLOGRAPH: reserved address type");
_contractTypeAddresses[contractType] = contractAddress;
Expand Down
10 changes: 5 additions & 5 deletions contracts/enforcer/HolographERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ import "../interface/HolographerInterface.sol";
import "../interface/HolographRegistryInterface.sol";
import "../interface/InitializableInterface.sol";
import "../interface/HolographInterfacesInterface.sol";
import "../interface/PA1DInterface.sol";
import "../interface/RoyaltyInterface.sol";
import "../interface/Ownable.sol";

/**
Expand Down Expand Up @@ -257,10 +257,10 @@ contract HolographERC721 is Admin, Owner, HolographERC721Interface, Initializabl
if (!skipInit) {
require(sourceContract.init(initCode) == InitializableInterface.init.selector, "ERC721: could not init source");
(bool success, bytes memory returnData) = _royalties().delegatecall(
abi.encodeWithSignature("initPA1D(bytes)", abi.encode(address(this), uint256(contractBps)))
abi.encodeWithSignature("initRoyalty(bytes)", abi.encode(address(this), uint256(contractBps)))
);
bytes4 selector = abi.decode(returnData, (bytes4));
require(success && selector == InitializableInterface.init.selector, "ERC721: coud not init PA1D");
require(success && selector == InitializableInterface.init.selector, "ERC721: coud not init Royalty");
}

_setInitialized();
Expand Down Expand Up @@ -297,7 +297,7 @@ contract HolographERC721 is Admin, Owner, HolographERC721Interface, Initializabl
}
if (
interfaces.supportsInterface(InterfaceType.ERC721, interfaceId) || // check global interfaces
interfaces.supportsInterface(InterfaceType.PA1D, interfaceId) || // check if royalties supports interface
interfaces.supportsInterface(InterfaceType.Royalty, interfaceId) || // check if royalties supports interface
erc165Contract.supportsInterface(interfaceId) // check if source supports interface
) {
return true;
Expand Down Expand Up @@ -969,7 +969,7 @@ contract HolographERC721 is Admin, Owner, HolographERC721Interface, Initializabl
fallback() external payable {
// we check if royalties support the function, send there, otherwise revert to source
address _target;
if (HolographInterfacesInterface(_interfaces()).supportsInterface(InterfaceType.PA1D, msg.sig)) {
if (HolographInterfacesInterface(_interfaces()).supportsInterface(InterfaceType.Royalty, msg.sig)) {
_target = _royalties();
assembly {
calldatacopy(0, 0, calldatasize())
Expand Down
60 changes: 30 additions & 30 deletions contracts/enforcer/PA1D.sol → contracts/enforcer/Royalty.sol
Original file line number Diff line number Diff line change
Expand Up @@ -107,41 +107,41 @@ import "../abstract/Owner.sol";

import "../interface/ERC20.sol";
import "../interface/InitializableInterface.sol";
import "../interface/PA1DInterface.sol";
import "../interface/RoyaltyInterface.sol";

import "../struct/ZoraBidShares.sol";

/**
* @title PA1D (CXIP)
* @title Royalty (CXIP)
* @author CXIP-Labs
* @notice A smart contract for providing royalty info, collecting royalties, and distributing it to configured payout wallets.
* @dev This smart contract is not intended to be used directly. Apply it to any of your ERC721 or ERC1155 smart contracts through a delegatecall fallback.
*/
contract PA1D is Admin, Owner, Initializable {
contract Royalty is Admin, Owner, Initializable {
/**
* @dev bytes32(uint256(keccak256('eip1967.Holograph.PA1D.defaultBp')) - 1)
* @dev bytes32(uint256(keccak256('eip1967.Holograph.Royalty.defaultBp')) - 1)
*/
bytes32 constant _defaultBpSlot = 0x3ab91e3c2ba71a57537d782545f8feb1d402b604f5e070fa6c3b911fc2f18f75;
bytes32 constant _defaultBpSlot = 0x84a6a6774d6ecfe3d26df0300765cd12a6975d410e5d59bfd3d17d7012a6d604;
/**
* @dev bytes32(uint256(keccak256('eip1967.Holograph.PA1D.defaultReceiver')) - 1)
* @dev bytes32(uint256(keccak256('eip1967.Holograph.Royalty.defaultReceiver')) - 1)
*/
bytes32 constant _defaultReceiverSlot = 0xfd430e1c7265cc31dbd9a10ce657e68878a41cfe179c80cd68c5edf961516848;
bytes32 constant _defaultReceiverSlot = 0x521109fa49e62d312d03a1ca2418f1599fa9d4155989a3b1083065f3683a3595;
/**
* @dev bytes32(uint256(keccak256('eip1967.Holograph.PA1D.initialized')) - 1)
* @dev bytes32(uint256(keccak256('eip1967.Holograph.Royalty.initialized')) - 1)
*/
bytes32 constant _initializedPaidSlot = 0x33a44e907d5bf333e203bebc20bb8c91c00375213b80f466a908f3d50b337c6c;
bytes32 constant _initializedRoyaltySlot = 0x3b31ec94793e1ee367b870e1cf5b600d34b5a816c3c26284b2197355160a2097;
/**
* @dev bytes32(uint256(keccak256('eip1967.Holograph.PA1D.payout.addresses')) - 1)
* @dev bytes32(uint256(keccak256('eip1967.Holograph.Royalty.payout.addresses')) - 1)
*/
bytes32 constant _payoutAddressesSlot = 0x700a541bc37f227b0d36d34e7b77cc0108bde768297c6f80f448f380387371df;
bytes32 constant _payoutAddressesSlot = 0x43f9e10caf7e996d882a109dd401a6e396536dba8dada0fc1f214275d4e00b42;
/**
* @dev bytes32(uint256(keccak256('eip1967.Holograph.PA1D.payout.bps')) - 1)
* @dev bytes32(uint256(keccak256('eip1967.Holograph.Royalty.payout.bps')) - 1)
*/
bytes32 constant _payoutBpsSlot = 0x7a62e8104cd2cc2ef6bd3a26bcb71428108fbe0e0ead6a5bfb8676781e2ed28d;
bytes32 constant _payoutBpsSlot = 0xa49d3946a91174f66018de9d2bdd14b5e58751f005c7dc36fdc4fa5b889d548b;

string constant _bpString = "eip1967.Holograph.PA1D.bp";
string constant _receiverString = "eip1967.Holograph.PA1D.receiver";
string constant _tokenAddressString = "eip1967.Holograph.PA1D.tokenAddress";
string constant _bpString = "eip1967.Holograph.Royalty.bp";
string constant _receiverString = "eip1967.Holograph.Royalty.receiver";
string constant _tokenAddressString = "eip1967.Holograph.Royalty.tokenAddress";

/**
* @notice Event emitted when setting/updating royalty info/fees. This is used by Rarible V1.
Expand All @@ -156,7 +156,7 @@ contract PA1D is Admin, Owner, Initializable {
* @dev Use this modifier to lock public functions that should not be accesible to non-owners.
*/
modifier onlyOwner() override {
require(isOwner(), "PA1D: caller not an owner");
require(isOwner(), "Royalty: caller not an owner");
_;
}

Expand All @@ -171,7 +171,7 @@ contract PA1D is Admin, Owner, Initializable {
* @param initPayload abi encoded payload to use for contract initilaization
*/
function init(bytes memory initPayload) external override returns (bytes4) {
require(!_isInitialized(), "PA1D: already initialized");
require(!_isInitialized(), "Royalty: already initialized");
assembly {
sstore(_adminSlot, caller())
sstore(_ownerSlot, caller())
Expand All @@ -182,17 +182,17 @@ contract PA1D is Admin, Owner, Initializable {
return InitializableInterface.init.selector;
}

function initPA1D(bytes memory initPayload) external returns (bytes4) {
function initRoyalty(bytes memory initPayload) external returns (bytes4) {
uint256 initialized;
assembly {
initialized := sload(_initializedPaidSlot)
initialized := sload(_initializedRoyaltySlot)
}
require(initialized == 0, "PA1D: already initialized");
require(initialized == 0, "Royalty: already initialized");
(address receiver, uint256 bp) = abi.decode(initPayload, (address, uint256));
setRoyalties(0, payable(receiver), bp);
initialized = 1;
assembly {
sstore(_initializedPaidSlot, initialized)
sstore(_initializedRoyaltySlot, initialized)
}
return InitializableInterface.init.selector;
}
Expand Down Expand Up @@ -387,7 +387,7 @@ contract PA1D is Admin, Owner, Initializable {
// adding 1x for each item in array to accomodate rounding errors
uint256 gasCost = (23300 * length) + length;
uint256 balance = address(this).balance;
require(balance - gasCost > 10000, "PA1D: Not enough ETH to transfer");
require(balance - gasCost > 10000, "Royalty: Not enough ETH to transfer");
balance = balance - gasCost;
uint256 sending;
// uint256 sent;
Expand All @@ -408,12 +408,12 @@ contract PA1D is Admin, Owner, Initializable {
uint256 length = addresses.length;
ERC20 erc20 = ERC20(tokenAddress);
uint256 balance = erc20.balanceOf(address(this));
require(balance > 10000, "PA1D: Not enough tokens to transfer");
require(balance > 10000, "Royalty: Not enough tokens to transfer");
uint256 sending;
//uint256 sent;
for (uint256 i = 0; i < length; i++) {
sending = ((bps[i] * balance) / 10000);
require(erc20.transfer(addresses[i], sending), "PA1D: Couldn't transfer token");
require(erc20.transfer(addresses[i], sending), "Royalty: Couldn't transfer token");
// sent = sent + sending;
}
}
Expand All @@ -432,11 +432,11 @@ contract PA1D is Admin, Owner, Initializable {
for (uint256 t = 0; t < tokenAddresses.length; t++) {
erc20 = ERC20(tokenAddresses[t]);
balance = erc20.balanceOf(address(this));
require(balance > 10000, "PA1D: Not enough tokens to transfer");
require(balance > 10000, "Royalty: Not enough tokens to transfer");
// uint256 sent;
for (uint256 i = 0; i < addresses.length; i++) {
sending = ((bps[i] * balance) / 10000);
require(erc20.transfer(addresses[i], sending), "PA1D: Couldn't transfer token");
require(erc20.transfer(addresses[i], sending), "Royalty: Couldn't transfer token");
// sent = sent + sending;
}
}
Expand All @@ -457,7 +457,7 @@ contract PA1D is Admin, Owner, Initializable {
break;
}
}
require(matched, "PA1D: sender not authorized");
require(matched, "Royalty: sender not authorized");
}
}

Expand All @@ -469,12 +469,12 @@ contract PA1D is Admin, Owner, Initializable {
* @param bps An array of the percentages that each address will receive from the royalty payouts.
*/
function configurePayouts(address payable[] memory addresses, uint256[] memory bps) public onlyOwner {
require(addresses.length == bps.length, "PA1D: missmatched array lenghts");
require(addresses.length == bps.length, "Royalty: missmatched array lenghts");
uint256 totalBp;
for (uint256 i = 0; i < addresses.length; i++) {
totalBp = totalBp + bps[i];
}
require(totalBp == 10000, "PA1D: bps down't equal 10000");
require(totalBp == 10000, "Royalty: bps down't equal 10000");
_setPayoutAddresses(addresses);
_setPayoutBps(bps);
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/enum/InterfaceType.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,5 @@ enum InterfaceType {
ERC20, // 1
ERC721, // 2
ERC1155, // 3
PA1D // 4
Royalty // 4
}
4 changes: 3 additions & 1 deletion contracts/interface/HolographTreasuryInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@

pragma solidity 0.8.13;

interface HolographTreasuryInterface {}
interface HolographTreasuryInterface {

}
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ pragma solidity 0.8.13;

import "../struct/ZoraBidShares.sol";

interface PA1DInterface {
function initPA1D(bytes memory data) external returns (bytes4);
interface RoyaltyInterface {
function initRoyalty(bytes memory data) external returns (bytes4);

function configurePayouts(address payable[] memory addresses, uint256[] memory bps) external;

Expand Down
18 changes: 9 additions & 9 deletions deploy/02_sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
MockERC721Receiver,
MockLZEndpoint,
Owner,
PA1D,
Royalty,
SampleERC20,
SampleERC721,
} from '../typechain-types';
Expand Down Expand Up @@ -206,10 +206,10 @@ const func: DeployFunction = async function (hre1: HardhatRuntimeEnvironment) {
const futureRoyaltiesAddress = await genesisDeriveFutureAddress(
hre,
salt,
'PA1D',
'Royalty',
generateInitCode(['address', 'uint256'], [zeroAddress, '0x' + '00'.repeat(32)])
);
hre.deployments.log('the future "PA1D" address is', futureRoyaltiesAddress);
hre.deployments.log('the future "Royalty" address is', futureRoyaltiesAddress);

// Future Holograph Utility Token
const currentNetworkType: NetworkType = networks[hre.networkName].type;
Expand Down Expand Up @@ -628,7 +628,7 @@ const func: DeployFunction = async function (hre1: HardhatRuntimeEnvironment) {
'0x' + web3.utils.asciiToHex('HolographERC1155').substring(2).padStart(64, '0'),
'0x' + web3.utils.asciiToHex('CxipERC721').substring(2).padStart(64, '0'),
'0x' + web3.utils.asciiToHex('CxipERC1155').substring(2).padStart(64, '0'),
'0x' + web3.utils.asciiToHex('PA1D').substring(2).padStart(64, '0'),
'0x' + web3.utils.asciiToHex('Royalty').substring(2).padStart(64, '0'),
],
]
),
Expand Down Expand Up @@ -781,19 +781,19 @@ const func: DeployFunction = async function (hre1: HardhatRuntimeEnvironment) {
global.__deployedHolographInterfaces = false;
}

// PA1D
// Royalty
let royaltiesDeployedCode: string = await hre.provider.send('eth_getCode', [futureRoyaltiesAddress, 'latest']);
if (royaltiesDeployedCode == '0x' || royaltiesDeployedCode == '') {
hre.deployments.log('"PA1D" bytecode not found, need to deploy"');
hre.deployments.log('"Royalty" bytecode not found, need to deploy"');
let royalties = await genesisDeployHelper(
hre,
salt,
'PA1D',
'Royalty',
generateInitCode(['address', 'uint256'], [deployer.address, '0x' + '00'.repeat(32)]),
futureRoyaltiesAddress
);
} else {
hre.deployments.log('"PA1D" is already deployed..');
hre.deployments.log('"Royalty" is already deployed..');
}
};

Expand All @@ -813,6 +813,6 @@ func.tags = [
'HolographTreasury',
'HolographTreasuryProxy',
'HolographInterfaces',
'PA1D',
'Royalty',
];
func.dependencies = ['HolographGenesis'];
8 changes: 4 additions & 4 deletions deploy/03_interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
ERC721TokenReceiver,
HolographInterfaces,
InitializableInterface,
PA1DInterface,
RoyaltyInterface,
} from '../typechain-types';

const web3 = new Web3();
Expand Down Expand Up @@ -271,10 +271,10 @@ const func: DeployFunction = async function (hre1: HardhatRuntimeEnvironment) {
// CollectionURI
functionHash('contractURI()'),
],
// PA1D
// Royalty
'4': [
// PA1D
functionHash('initPA1D(bytes)'),
// Royalty
functionHash('initRoyalty(bytes)'),
functionHash('configurePayouts(address[],uint256[])'),
functionHash('getPayoutInfo()'),
functionHash('getEthPayout()'),
Expand Down
20 changes: 10 additions & 10 deletions deploy/11_register_templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,23 +126,23 @@ const func: DeployFunction = async function (hre1: HardhatRuntimeEnvironment) {
const futureRoyaltiesAddress = await genesisDeriveFutureAddress(
hre,
salt,
'PA1D',
'Royalty',
generateInitCode(['address', 'uint256'], [zeroAddress, '0x' + '00'.repeat(32)])
);
hre.deployments.log('the future "PA1D" address is', futureRoyaltiesAddress);
hre.deployments.log('the future "Royalty" address is', futureRoyaltiesAddress);

const pa1dHash = '0x' + web3.utils.asciiToHex('PA1D').substring(2).padStart(64, '0');
if ((await holographRegistry.getContractTypeAddress(pa1dHash)) != futureRoyaltiesAddress) {
const pa1dTx = await holographRegistry
.setContractTypeAddress(pa1dHash, futureRoyaltiesAddress, {
const royaltyHash = '0x' + web3.utils.asciiToHex('Royalty').substring(2).padStart(64, '0');
if ((await holographRegistry.getContractTypeAddress(royaltyHash)) != futureRoyaltiesAddress) {
const royaltyTx = await holographRegistry
.setContractTypeAddress(royaltyHash, futureRoyaltiesAddress, {
nonce: await hre.ethers.provider.getTransactionCount(deployer),
})
.catch(error);
hre.deployments.log('Transaction hash:', pa1dTx.hash);
await pa1dTx.wait();
hre.deployments.log(`Registered "PA1D" to: ${await holographRegistry.getContractTypeAddress(pa1dHash)}`);
hre.deployments.log('Transaction hash:', royaltyTx.hash);
await royaltyTx.wait();
hre.deployments.log(`Registered "Royalty" to: ${await holographRegistry.getContractTypeAddress(royaltyHash)}`);
} else {
hre.deployments.log('"PA1D" is already registered');
hre.deployments.log('"Royalty" is already registered');
}
};

Expand Down
Loading

0 comments on commit b2e9584

Please sign in to comment.