Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup Files #4

Merged
merged 3 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Paxos Technology Solutions, LLC
Copyright (c) 2024 Paxos Technology Solutions, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
41 changes: 0 additions & 41 deletions Makefile

This file was deleted.

57 changes: 23 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,24 @@ Paxos-issued USD-collateralized ERC20 stablecoin public smart contract repositor

https://github.com/paxosglobal/paxos-token-contract

### Roles and Addresses
### Roles

| Role | Address |
| ------------------------------ | ------------------------------------------ |
| DEFAULT_ADMIN_ROLE | TBD |
| PAUSE_ROLE | TBD |
| ASSET_PROTECTION_ROLE | TBD |
| SUPPLY_CONTROLLER_MANAGER_ROLE | TBD |
| SUPPLY_CONTROLLER_ROLE | TBD |
| Role |
| ------------------------------ |
| DEFAULT_ADMIN_ROLE |
| PAUSE_ROLE |
| ASSET_PROTECTION_ROLE |
| SUPPLY_CONTROLLER_MANAGER_ROLE |
| SUPPLY_CONTROLLER_ROLE |

To guard against centralized control, the addresses above utilize multisignature contracts ([source](https://github.com/paxosglobal/simple-multisig)). Any change requires the presence of a quorum of signers in the same physical location, ensuring that no individual signer can unilaterally influence a change.

### ABI, Address, and Verification
### ABI and Addresses

The contract abi is in `PaxosToken.abi`, which is the imlementation contract abi.
The contract abi is in `PaxosToken.abi`, which is the implementation contract abi.

Interaction with token is done at the address of the proxy. Below is the table which list out all our contract addresses.

| Token | Proxy-address | Implementation-Address |
| :-------------: |:-------------:| :-----:|
| USDP | 0x000000000000000000000000000000000000000 | 0x000000000000000000000000000000000000000 |
Interaction with token is done at the address of the proxy. Deployed token addresses can be found in
the [Paxos docs](https://docs.paxos.com/stablecoin).

## Contract Specification

Expand Down Expand Up @@ -91,10 +88,6 @@ While paused, the supply controller retains the ability to mint and burn tokens.

### Asset Protection Role

Paxos Trust Company is regulated by the New York Department of Financial Services (NYDFS). As required by the regulator,
Paxos must have a role for asset protection to freeze or seize the assets of a criminal party when required to do so by
law, including by court order or other legal process.

The `ASSET_PROTECTION_ROLE` can freeze and unfreeze the token balance of any address on chain.
It can also wipe the balance of an address after it is frozen
to allow the appropriate authorities to seize the backing assets.
Expand All @@ -105,7 +98,7 @@ via `isFrozen(address who)`.

### Delegate Transfer

To facilitate gas-less transactions, we have implemented [EIP-3009](https://eips.ethereum.org/EIPS/eip-3009) and (EIP-2612)[https://eips.ethereum.org/EIPS/eip-2612].
To facilitate gas-less transactions, we have implemented [EIP-3009](https://eips.ethereum.org/EIPS/eip-3009) and [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612).

#### EIP-3009
The public functions, `transferWithAuthorization` and `transferWithAuthorizationBatch` (for multiple transfers request), allows a spender(delegate) to transfer tokens on behalf of the sender, with condition that a signature, conforming to [EIP-712](https://eips.ethereum.org/EIPS/eip-712), is provided by the respective sender.
Expand Down Expand Up @@ -175,7 +168,16 @@ _in the context of the proxy storage_. This way the implementation pointer can
be changed to a different implementation contract while still keeping the same
data and contract address, which are really for the proxy contract.

The proxy used here is AdminUpgradeabilityProxy from ZeppelinOS.
USDP and PYUSD use `AdminUpgradeabilityProxy` from OpenZeppelin.

USDG and SupplyControl use `UUPSUpgradeable` from OpenZeppelin.

`UUPSUpgradeable` is a newer proxy pattern which
has some advantages over `AdminUpgradeabilityProxy`. One issue with `AdminUpgradeabilityProxy` is the proxy admin
cannot call any of the implementation functions which means the proxy admin must be a separate address
from the DEFAULT_ADMIN_ROLE. This is not an issue with `UUPSUpgradeable`. Another advantage is updating
the proxy admin in `UUPSUpgradeable` is a two step process due to using OpenZeppelin's AccessControlDefaultAdmin.
However, in `AdminUpgradeabilityProxy` it's one step which is more dangerous.

## Upgrade Process

Expand All @@ -186,19 +188,6 @@ it can all be done in one transaction. You must first deploy a copy of the new i
contract, which is automatically paused by its constructor to help avoid accidental calls directly
to the proxy contract.

## Bytecode verification
[comment]: <> (TODO: ref: `@` -> Add implementation address for line 142)

The proxy contract and implementation contracts are verified on etherscan at the following links:
https://etherscan.io/token/0x6c3ea9036406852006290770bedfcaba0e23a0e8
https://etherscan.io/token/`@`

Because the implementation address in the proxy is a private variable,
verifying that this is the proxy being used requires reading contract
storage directly. The contract storage slot address is `0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3`.

`npx hardhat --network ${NETWORK} run scripts/getImplementationAddress.js`

## Contract Tests
Install dependencies:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ library SafeMath {
}
}

// File: contracts/XYZImplementation.sol
// File: contracts/PaxosToken.sol

pragma solidity ^0.4.24;
pragma experimental "v0.5.0";



/**
* @title XYZImplementation
* @title PaxosToken
* @dev this contract is a Pausable ERC20 token with Burn and Mint
* controlled by a central SupplyController. By implementing XYZImplementation
* controlled by a central SupplyController. By implementing PaxosToken
* this contract also includes external methods for setting
* a new implementation contract for the Proxy.
* NOTE: The storage defined here will actually be held in the Proxy
Expand All @@ -48,7 +48,7 @@ pragma experimental "v0.5.0";
* Any call to transfer against this contract should fail
* with insufficient funds since no tokens will be issued there.
*/
contract XYZImplementation {
contract PaxosToken {

/**
* MATH
Expand All @@ -66,8 +66,8 @@ contract XYZImplementation {
// ERC20 BASIC DATA
mapping(address => uint256) internal balances;
uint256 internal totalSupply_;
string public constant name = "Hopper"; // solium-disable-line
string public constant symbol = "XYZ"; // solium-disable-line uppercase
string public constant name = "PaxosToken USD"; // solium-disable-line
string public constant symbol = "PaxosToken"; // solium-disable-line uppercase
uint8 public constant decimals = 6; // solium-disable-line uppercase

// ERC20 DATA
Expand Down Expand Up @@ -383,11 +383,11 @@ contract XYZImplementation {
}

/**
* @dev Reclaim all XYZ at the contract address.
* This sends the XYZ tokens that this contract add holding to the owner.
* @dev Reclaim all tokens at the contract address.
* This sends the tokens that this contract add holding to the owner.
* Note: this is not affected by freeze constraints.
*/
function reclaimXYZ() external onlyOwner {
function reclaimToken() external onlyOwner {
uint256 _balance = balances[this];
balances[this] = 0;
balances[owner] = balances[owner].add(_balance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,15 @@ abstract contract EIP3009 is PaxosBaseAbstract, EIP712Domain {
}
}

// File: contracts/XYZImplementation.sol
// File: contracts/PaxosToken.sol

pragma solidity ^0.8.17;


/**
* @title XYZImplementation
* @title PaxosToken
* @dev this contract is a Pausable ERC20 token with Burn and Mint
* controlled by a central SupplyController. By implementing XYZImplementation
* controlled by a central SupplyController. By implementing PaxosToken
* this contract also includes external methods for setting
* a new implementation contract for the Proxy.
* NOTE: The storage defined here will actually be held in the Proxy
Expand All @@ -504,7 +504,7 @@ pragma solidity ^0.8.17;
* Any call to transfer against this contract should fail
* with insufficient funds since no tokens will be issued there.
*/
contract XYZImplementation is PaxosBaseAbstract{
contract PaxosToken is PaxosBaseAbstract{

/**
* DATA
Expand All @@ -516,8 +516,8 @@ contract XYZImplementation is PaxosBaseAbstract{
// ERC20 BASIC DATA
mapping(address => uint256) internal balances;
uint256 internal totalSupply_;
string public constant name = "XYZ USD"; // solhint-disable-line const-name-snakecase
string public constant symbol = "XYZ"; // solhint-disable-line const-name-snakecase
string public constant name = "PaxosToken USD"; // solhint-disable-line const-name-snakecase
string public constant symbol = "PaxosToken"; // solhint-disable-line const-name-snakecase
uint8 public constant decimals = 6; // solhint-disable-line const-name-snakecase

// ERC20 DATA
Expand Down Expand Up @@ -556,7 +556,7 @@ contract XYZImplementation is PaxosBaseAbstract{
// solhint-disable-next-line var-name-mixedcase
bytes32 public EIP712_DOMAIN_HASH_DEPRECATED;
// Storage gap: https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps
uint256[25] __gap_XYZImplementation;
uint256[25] __gap_PaxosToken;

/**
* EVENTS
Expand Down Expand Up @@ -828,11 +828,11 @@ contract XYZImplementation is PaxosBaseAbstract{
}

/**
* @dev Reclaim all XYZ at the contract address.
* This sends the XYZ tokens that this contract add holding to the owner.
* @dev Reclaim all tokens at the contract address.
* This sends the tokens that this contract add holding to the owner.
* Note: this is not affected by freeze constraints.
*/
function reclaimXYZ() external onlyOwner {
function reclaimToken() external onlyOwner {
uint256 _balance = balances[address(this)];
balances[address(this)] = 0;
balances[owner] += _balance;
Expand Down Expand Up @@ -1046,7 +1046,7 @@ contract XYZImplementation is PaxosBaseAbstract{

}

// File: contracts/XYZImplementationV1.sol
// File: contracts/PaxosTokenV1.sol

pragma solidity ^0.8.17;

Expand All @@ -1055,9 +1055,9 @@ pragma solidity ^0.8.17;


/**
* @title XYZImplementationV1
* @title PaxosTokenV1
* @dev this contract is a Pausable ERC20 token with Burn and Mint
* controlled by a central SupplyController. By implementing XYZImplementationV1
* controlled by a central SupplyController. By implementing PaxosTokenV1
* this contract also includes external methods for setting
* a new implementation contract for the Proxy.
* NOTE: The storage defined here will actually be held in the Proxy
Expand All @@ -1066,7 +1066,7 @@ pragma solidity ^0.8.17;
* Any call to transfer against this contract should fail
* with insufficient funds since no tokens will be issued there.
*/
contract XYZImplementationV1 is XYZImplementation, EIP2612, EIP3009 {
contract PaxosTokenV1 is PaxosToken, EIP2612, EIP3009 {
constructor() {
initializeEIP712DomainSeparator();
}
Expand All @@ -1075,6 +1075,6 @@ contract XYZImplementationV1 is XYZImplementation, EIP2612, EIP3009 {
* @dev To be called when upgrading the contract using upgradeAndCall and during initialization of contract.
*/
function initializeEIP712DomainSeparator() public {
DOMAIN_SEPARATOR = EIP712.makeDomainSeparator("XYZ", "1");
DOMAIN_SEPARATOR = EIP712.makeDomainSeparator("PaxosToken", "1");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils
import { PaxosTokenV2 } from "./../PaxosTokenV2.sol";

/**
* @title USDX Smart contract
* @title USDG Smart contract
* @dev This contract is a {PaxosTokenV2-PaxosTokenV2} ERC20 token.
* @custom:security-contact [email protected]
*/
contract USDX is PaxosTokenV2, UUPSUpgradeable {
contract USDG is PaxosTokenV2, UUPSUpgradeable {
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return "USD Token";
return "Global Dollar";
}

/**
* @dev Returns the symbol of the token.
*/
function symbol() public view virtual override returns (string memory) {
return "USDX";
return "USDG";
}

/**
Expand Down
3 changes: 2 additions & 1 deletion scripts/deploy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { ethers } = require("hardhat");
const { PrintDeployerDetails, PrintContractDetails } = require('./utils');
const { PrintDeployerDetails, PrintContractDetails, ValidateEnvironmentVariables } = require('./utils');

const { TOKEN_ADMIN_ADDRESS, TOKEN_OWNER_ADDRESS, PAUSER_ADDRESS, ASSET_PROTECTOR_ADDRESS, TOKEN_CONTRACT_NAME } = process.env;

Expand All @@ -14,6 +14,7 @@ const initializerArgs = [
]

async function main() {
ValidateEnvironmentVariables([...initializerArgs, TOKEN_CONTRACT_NAME])
PrintDeployerDetails();

console.log("\nDeploying Implementation contract...")
Expand Down
3 changes: 2 additions & 1 deletion scripts/deployImplementation.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const { ethers } = require("hardhat");
const { TOKEN_CONTRACT_NAME} = process.env;

const { PrintDeployerDetails, PrintContractDetails } = require('./utils');
const { PrintDeployerDetails, PrintContractDetails, ValidateEnvironmentVariables } = require('./utils');

async function main() {
ValidateEnvironmentVariables([TOKEN_CONTRACT_NAME])
PrintDeployerDetails();

console.log("\nDeploying Implementation contract...")
Expand Down
Loading