Skip to content

Instantly share code, notes, and snippets.

@pgebheim
Forked from justinbarry/WrappedShareTokenFactory.sol
Last active February 12, 2021 05:06
Show Gist options
  • Save pgebheim/3d4ece4ca3d3c789d2bdf8e309021f8e to your computer and use it in GitHub Desktop.
Save pgebheim/3d4ece4ca3d3c789d2bdf8e309021f8e to your computer and use it in GitHub Desktop.
ragma solidity 0.5.15;
pragma experimental ABIEncoderV2;
import "ROOT/trading/wrappedShareToken/WrappedShareToken.sol";
import 'ROOT/para/interfaces/IParaShareToken.sol';
import 'ROOT/libraries/TokenId.sol';
/**
* @dev This is a factory that creates Wrappers around ERC1155 shareTokens generated by Augur
* @author yashnaman
* as shares on outcomes of a markets.
* For every outcome there will be one wrapper.
*/
contract WrappedShareTokenFactory {
IParaShareToken public shareToken;
IERC20 public cash;
mapping(uint256 => address) public wrappers;
event WrapperCreated(uint256 indexed tokenId, address tokenAddress, string symbol);
/**@dev sets value for {shareToken} and {cash}
* @param _shareToken address of shareToken associated with a augur universe
*/
constructor(IParaShareToken _shareToken, IERC20 _cash) public {
shareToken = _shareToken;
cash = _shareToken.cash();
}
/**@dev creates new ERC20 wrappers for a outcome of a market
*@param _tokenId token id associated with a outcome of a market
*@param _name a descriptive name mentioning market and outcome
*@param _symbol symbol for the ERC20 wrapper
*@param decimals decimals for the ERC20 wrapper
*/
function createWrappedShareToken(
uint256 _tokenId,
string memory _symbol
) public returns (WrappedShareToken) {
address _wrappedShareTokenAddress = calculateShareTokenAddress(
_tokenId,
_symbol,
);
if(_wrappedShareTokenAddress.exists()) {
return WrappedShareToken(_wrappedShareTokenAddress);
}
{
bytes32 _salt = keccak256(abi.encodePacked(shareToken, cash,_tokenId, _symbol, _decimals));
bytes memory _code = abi.encodePacked(type(WrappedShareToken).creationCode);
assembly {
_wrappedShareTokenAddress := create2(0x0, add(_code, 0x20), mload(_code), _salt);
if iszero(extcodesize(_code)) { revert(0,0) }
}
}
// Wrapped Share Token has to be Initializable -- see AugurWallet.sol
WrappedShareToken _wrappedShareToken = WrappedShareToken(_wrappedShareTokenAddress);
_wrappedShareToken.initialize(
shareToken,
cash,
_tokenId,
_symbol
);
emit WrapperCreated(_tokenId, address(WrappedShareToken), _symbol);
return _wrappedShareToken;
}
/**@dev creates new ERC20 wrappers for multiple tokenIds*/
function createWrappedShareTokens(
uint256[] memory _tokenIds,
string[] memory _symbols,
) public returns (addresss[] memory _wrappedShareTokens){
require(
_tokenIds.length == _names.length &&
_tokenIds.length == _symbols.length
);
_wrappedShareToken = new address[](_tokenIds.length);
for (uint256 i = 0; i < _tokenIds.length; i++) {
_wrappedShareToken[i] = createWrappedShareToken(_tokenIds[i], _symbols[i]);
}
}
/**@dev A function that wraps ERC1155s shareToken into ERC20s
* Requirements:
*
* - msg.sender has setApprovalForAll to this contract
* @param _tokenId token id associated with a outcome of a market
* @param _account account the newly minted ERC20s will go to
* @param _amount amount of tokens to be wrapped
*/
function wrapTokens(
address _tokenId,
address _account,
uint256 _amount
) public {
WrappedShareToken WrappedShareToken = WrappedShareToken(wrappers[_tokenId]);
shareToken.unsafeTransferFrom(
msg.sender,
address(WrappedShareToken),
_tokenId,
_amount
);
WrappedShareToken.wrapTokens(_account, _amount);
}
/**@dev A function that burns ERC20s and gives back ERC1155s
* Requirements:
*
* - msg.sender has more than _amount of ERC20 tokens associated with _tokenId.
* - if the market has finalized then it is advised that you call claim() on WrappedShareToken
* contract associated with the winning outcome
* @param _tokenId token id associated with a outcome of a market
* @param _amount amount of tokens to be unwrapped
*/
function unWrapTokens(uint256 _tokenId, string memory _symbol, uint256 _amount) public {
WrappedShareToken _wrappedShareToken = WrappedShareToken(calculateShareTokenAddress(_tokenId, _symbol));
WrappedShareToken.unWrapTokens(msg.sender, _amount);
}
/**@dev wraps multiple tokens */
function wrapMultipleTokens(
uint256[] memory _tokenIds,
address _account,
uint256[] memory _amounts
) public {
for (uint256 i = 0; i < _tokenIds.length; i++) {
wrapTokens(_tokenIds[i], _account, _amounts[i]);
}
}
/**@dev unwraps multiple tokens */
function unWrapMultipleTokens(
uint256[] memory _tokenIds,
uint256[] memory _amounts
) public {
for (uint256 i = 0; i < _tokenIds.length; i++) {
unWrapTokens(_tokenIds[i], _amounts[i]);
}
}
/**@dev get the address for a particular WrappedShareToken
*@param _tokenId token id associated with a outcome of a market
*@param _name a descriptive name mentioning market and outcome
*@param _symbol symbol for the ERC20 wrapper
*@param decimals decimals for the ERC20 wrapper
*/
function calculateShareTokenAddress(
uint256 _tokenId,
string memory _symbol,
) public view returns (address) {
bytes1 _const = 0xff;
bytes32 _salt = keccak256(abi.encodePacked(shareToken, cash, _tokenId, _symbol));
return address(uint160(uint256(keccak256(abi.encodePacked(
_const,
address(this),
_salt,
keccak256(abi.encodePacked(type(WrappedShareToken).creationCode))
)))));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment