Documented contract
This commit is contained in:
parent
7ec80a2270
commit
a3cba3d034
|
@ -4,6 +4,7 @@ import "./SpaceshipToken.sol";
|
||||||
import "zeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol";
|
import "zeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @title Escrow para compra venta del token
|
||||||
contract SpaceshipMarketplace is ERC721Holder {
|
contract SpaceshipMarketplace is ERC721Holder {
|
||||||
|
|
||||||
// Esta estructura guarda informacion sobre las ventas
|
// Esta estructura guarda informacion sobre las ventas
|
||||||
|
@ -13,27 +14,32 @@ contract SpaceshipMarketplace is ERC721Holder {
|
||||||
address owner;
|
address owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceshipToken token;
|
SpaceshipToken public token;
|
||||||
|
|
||||||
Sale[] public sales;
|
Sale[] public sales;
|
||||||
|
|
||||||
mapping(uint => uint) spaceshipToSale;
|
mapping(uint => uint) public spaceshipToSale;
|
||||||
|
|
||||||
event NewSale(uint indexed spaceshipId, uint price, uint saleId);
|
event NewSale(uint indexed spaceshipId, uint price, uint saleId);
|
||||||
|
|
||||||
event ShipSold(uint indexed spaceshipId, uint price, address indexed oldOwner, address indexed newOwner);
|
event ShipSold(uint indexed spaceshipId, uint price, address indexed oldOwner, address indexed newOwner);
|
||||||
|
|
||||||
|
/// @notice Constructor
|
||||||
constructor(SpaceshipToken _token) public {
|
/// @param _token Direccion del token
|
||||||
token = _token;
|
constructor(address _token) public {
|
||||||
|
token = SpaceshipToken(_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buy(uint _saleId) payable {
|
/// @notice Comprar token
|
||||||
|
/// @param _saleId Id de la venta que se desea
|
||||||
|
function buy(uint _saleId) public payable {
|
||||||
Sale storage s = sales[_saleId];
|
Sale storage s = sales[_saleId];
|
||||||
|
|
||||||
// TODO: descomentar esto para evitar que el dueno compre su propia nave
|
// TODO: descomentar esto para evitar que el dueno compre su propia nave
|
||||||
// require(s.owner != msg.sender);
|
// require(s.owner != msg.sender);
|
||||||
require(msg.value >= s.price);
|
require(msg.value >= s.price);
|
||||||
|
|
||||||
|
// Devolvemos el sobrante
|
||||||
uint refund = msg.value - s.price;
|
uint refund = msg.value - s.price;
|
||||||
if(refund > 0)
|
if(refund > 0)
|
||||||
msg.sender.transfer(refund);
|
msg.sender.transfer(refund);
|
||||||
|
@ -47,14 +53,16 @@ contract SpaceshipMarketplace is ERC721Holder {
|
||||||
token.approve(msg.sender, s.spaceshipId);
|
token.approve(msg.sender, s.spaceshipId);
|
||||||
token.safeTransferFrom(address(this), msg.sender, s.spaceshipId);
|
token.safeTransferFrom(address(this), msg.sender, s.spaceshipId);
|
||||||
|
|
||||||
// Eliminamos la venta // TODO: reorder
|
// Eliminamos la venta
|
||||||
delete spaceshipToSale[s.spaceshipId];
|
delete spaceshipToSale[s.spaceshipId];
|
||||||
|
|
||||||
Sale replacer = sales[sales.length - 1];
|
Sale replacer = sales[sales.length - 1];
|
||||||
sales[_saleId] = replacer;
|
sales[_saleId] = replacer;
|
||||||
sales.length--;
|
sales.length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Publicar token para venta
|
||||||
|
/// @param _spaceshipId Id del token
|
||||||
|
/// @param _price Precio de venta
|
||||||
function forSale(uint _spaceshipId, uint _price){
|
function forSale(uint _spaceshipId, uint _price){
|
||||||
// Solo se pueden vender tus propias naves
|
// Solo se pueden vender tus propias naves
|
||||||
require(token.ownerOf(_spaceshipId) == msg.sender);
|
require(token.ownerOf(_spaceshipId) == msg.sender);
|
||||||
|
@ -68,6 +76,7 @@ contract SpaceshipMarketplace is ERC721Holder {
|
||||||
owner: msg.sender
|
owner: msg.sender
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Agregamos el token a la lista de vtokens en venta
|
||||||
uint saleId = sales.push(s) - 1;
|
uint saleId = sales.push(s) - 1;
|
||||||
|
|
||||||
spaceshipToSale[_spaceshipId] = saleId;
|
spaceshipToSale[_spaceshipId] = saleId;
|
||||||
|
@ -75,6 +84,8 @@ contract SpaceshipMarketplace is ERC721Holder {
|
||||||
emit NewSale(_spaceshipId, _price, saleId);
|
emit NewSale(_spaceshipId, _price, saleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Retirar token de listado de venta
|
||||||
|
/// @param _spaceshipId Id del token
|
||||||
function withdraw(uint _spaceshipId){
|
function withdraw(uint _spaceshipId){
|
||||||
require(sales[spaceshipToSale[_spaceshipId]].owner == msg.sender);
|
require(sales[spaceshipToSale[_spaceshipId]].owner == msg.sender);
|
||||||
|
|
||||||
|
@ -86,6 +97,7 @@ contract SpaceshipMarketplace is ERC721Holder {
|
||||||
token.safeTransferFrom(address(this), msg.sender, _spaceshipId);
|
token.safeTransferFrom(address(this), msg.sender, _spaceshipId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Cantidad de tokens a la venta
|
||||||
function nSale() public view returns(uint) {
|
function nSale() public view returns(uint) {
|
||||||
return sales.length;
|
return sales.length;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
pragma solidity 0.4.24;
|
pragma solidity 0.4.24;
|
||||||
|
|
||||||
import "zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
|
import "zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
|
||||||
import 'zeppelin-solidity/contracts/ownership/Ownable.sol';
|
import "zeppelin-solidity/contracts/ownership/Ownable.sol";
|
||||||
|
|
||||||
/**
|
|
||||||
@title Contrato base para Mexico Workshop
|
/// @title Contrato base para Mexico Workshop
|
||||||
@dev En Status tambien hablamos espanol ;)
|
/// @dev En Status tambien hablamos espanol ;)
|
||||||
*/
|
|
||||||
contract SpaceshipToken is ERC721Token("CryptoSpaceships", "CST"), Ownable {
|
contract SpaceshipToken is ERC721Token("CryptoSpaceships", "CST"), Ownable {
|
||||||
|
|
||||||
/// @dev Estructura que representa nuestra nave spacial
|
// Estructura que representa nuestra nave spacial
|
||||||
struct Spaceship {
|
struct Spaceship {
|
||||||
bytes metadataHash; // IPFS Hash
|
bytes metadataHash; // IPFS Hash
|
||||||
uint8 energy;
|
uint8 energy;
|
||||||
|
@ -23,8 +22,13 @@ contract SpaceshipToken is ERC721Token("CryptoSpaceships", "CST"), Ownable {
|
||||||
// Precio de las naves
|
// Precio de las naves
|
||||||
mapping(uint => uint) public spaceshipPrices;
|
mapping(uint => uint) public spaceshipPrices;
|
||||||
uint[] public shipsForSale;
|
uint[] public shipsForSale;
|
||||||
mapping(uint => uint) indexes; // shipId => shipForSale
|
mapping(uint => uint) public indexes; // shipId => shipForSale
|
||||||
|
|
||||||
|
/// @notice Crear un tocken
|
||||||
|
/// @param _metadataHash IPFS hash que contiene la metadata del token
|
||||||
|
/// @param _energy Atributo: Energia
|
||||||
|
/// @param _lasers Atributo: Lasers
|
||||||
|
/// @param _price Precio de venta del token
|
||||||
function mint(bytes _metadataHash,
|
function mint(bytes _metadataHash,
|
||||||
uint8 _energy,
|
uint8 _energy,
|
||||||
uint8 _lasers,
|
uint8 _lasers,
|
||||||
|
@ -52,10 +56,14 @@ contract SpaceshipToken is ERC721Token("CryptoSpaceships", "CST"), Ownable {
|
||||||
_mint(address(this), spaceshipId);
|
_mint(address(this), spaceshipId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Obtener cantidad de naves a la venta
|
||||||
|
/// @return Cantidad
|
||||||
function shipsForSaleN() public view returns(uint) {
|
function shipsForSaleN() public view returns(uint) {
|
||||||
return shipsForSale.length;
|
return shipsForSale.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Comprar nave
|
||||||
|
/// @param _spaceshipId Id del token a comprar
|
||||||
function buySpaceship(uint _spaceshipId) public payable {
|
function buySpaceship(uint _spaceshipId) public payable {
|
||||||
// Solo se pueden comprar las naves cuyo dueno sea el contrato
|
// Solo se pueden comprar las naves cuyo dueno sea el contrato
|
||||||
require(ownerOf(_spaceshipId) == address(this));
|
require(ownerOf(_spaceshipId) == address(this));
|
||||||
|
@ -63,55 +71,57 @@ contract SpaceshipToken is ERC721Token("CryptoSpaceships", "CST"), Ownable {
|
||||||
// Se debe enviar al menos el precio de la nave
|
// Se debe enviar al menos el precio de la nave
|
||||||
require(msg.value != 0);
|
require(msg.value != 0);
|
||||||
|
|
||||||
// Transferimos la
|
// Approvamos directamente para evitar tener que crear una transaccion extra
|
||||||
// Approbamos directamente para evitar tener que crear una transaccion extra
|
// y luego enviamos la nave a quien origino la transaccion
|
||||||
tokenApprovals[_spaceshipId] = msg.sender;
|
tokenApprovals[_spaceshipId] = msg.sender;
|
||||||
safeTransferFrom(address(this), msg.sender, _spaceshipId);
|
safeTransferFrom(address(this), msg.sender, _spaceshipId);
|
||||||
|
|
||||||
// La eliminamos de la lista para venta
|
// La eliminamos de la lista para venta
|
||||||
|
// Esto se ve un poco mas complicado de lo necesario,
|
||||||
|
// Pero es para borrar elementos del arreglo de forma eficiente
|
||||||
uint256 replacer = shipsForSale[shipsForSale.length - 1];
|
uint256 replacer = shipsForSale[shipsForSale.length - 1];
|
||||||
uint256 pos = indexes[_spaceshipId];
|
uint256 pos = indexes[_spaceshipId];
|
||||||
shipsForSale[pos] = replacer;
|
shipsForSale[pos] = replacer;
|
||||||
indexes[replacer] = pos;
|
indexes[replacer] = pos;
|
||||||
shipsForSale.length--;
|
shipsForSale.length--;
|
||||||
|
|
||||||
|
// Reembolsamos el sobrante
|
||||||
uint refund = msg.value - spaceshipPrices[_spaceshipId];
|
uint refund = msg.value - spaceshipPrices[_spaceshipId];
|
||||||
if (refund > 0)
|
if (refund > 0)
|
||||||
msg.sender.transfer(refund);
|
msg.sender.transfer(refund);
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdrawBalance() external onlyOwner {
|
/// @notice Retirar balance por compras hechas
|
||||||
|
function withdrawBalance() public onlyOwner {
|
||||||
owner.transfer(address(this).balance);
|
owner.transfer(address(this).balance);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAttributes(uint _spaceshipId) public view returns (
|
/// @notice Obtener metadata
|
||||||
uint8 energy,
|
/// @param _spaceshipId Id del token
|
||||||
uint8 lasers,
|
/// @return Direccion desde donde obtener la metadata
|
||||||
uint8 shield
|
|
||||||
){
|
|
||||||
Spaceship storage s = spaceships[_spaceshipId];
|
|
||||||
|
|
||||||
energy = s.energy;
|
|
||||||
lasers = s.lasers;
|
|
||||||
shield = s.shield;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Obtain metadata
|
|
||||||
|
|
||||||
function tokenURI(uint256 _spaceshipId) public view returns (string) {
|
function tokenURI(uint256 _spaceshipId) public view returns (string) {
|
||||||
Spaceship storage s = spaceships[_spaceshipId];
|
Spaceship storage s = spaceships[_spaceshipId];
|
||||||
return strConcat("https://ipfs.io/ipfs/", string(s.metadataHash));
|
return strConcat("https://ipfs.io/ipfs/", string(s.metadataHash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Concatenar strings
|
||||||
|
/// @dev La concatenacion por strings por ahora debe hacerse manual o usando librerias
|
||||||
|
/// @param _a Primer string
|
||||||
|
/// @param _b Segundo string
|
||||||
|
/// @return String concatenado
|
||||||
function strConcat(string _a, string _b) private returns (string) {
|
function strConcat(string _a, string _b) private returns (string) {
|
||||||
bytes memory _ba = bytes(_a);
|
bytes memory _ba = bytes(_a);
|
||||||
bytes memory _bb = bytes(_b);
|
bytes memory _bb = bytes(_b);
|
||||||
string memory ab = new string(_ba.length + _bb.length);
|
string memory ab = new string(_ba.length + _bb.length);
|
||||||
bytes memory bab = bytes(ab);
|
bytes memory bab = bytes(ab);
|
||||||
uint k = 0;
|
uint k = 0;
|
||||||
for (uint i = 0; i < _ba.length; i++) bab[k++] = _ba[i];
|
|
||||||
for (i = 0; i < _bb.length; i++) bab[k++] = _bb[i];
|
for (uint i = 0; i < _ba.length; i++)
|
||||||
|
bab[k++] = _ba[i];
|
||||||
|
|
||||||
|
for (i = 0; i < _bb.length; i++)
|
||||||
|
bab[k++] = _bb[i];
|
||||||
|
|
||||||
return string(bab);
|
return string(bab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue