diff --git a/SmartContracts/ProofOfExistence.sol b/SmartContracts/ProofOfExistence.sol
index ee4f8ed179974516b26899a0ee2d770172504486..02d88499293435471fa06b4ce43988772e41a80d 100644
--- a/SmartContracts/ProofOfExistence.sol
+++ b/SmartContracts/ProofOfExistence.sol
@@ -1,29 +1,56 @@
 pragma solidity ^0.4.24;
 
-contract ProofOfExistence {
+contract Stamper {
+    event Stamped(address indexed from, string indexed hash, string indexed ots);
+
+    event Deploy(address indexed from);
+    event SelfDestroy(address indexed from);
+
     struct Dato {
         uint blockNumber;
-        uint256 hash;
+        string hash;
     }
-    mapping (uint256 => Dato) private hashstore;
+    mapping (string => Dato) private hashstore;
+    address owner;
 
+    constructor() public {
+        owner = msg.sender;
+        emit Deploy(msg.sender);
+    }
 
-    function stamp(uint256 ots, uint256 file_hash) public {
-        hashstore[ots] = Dato({blockNumber: block.number, hash: file_hash});
+    function stamp(string ots, string file_hash) public {
+        if (hashstore[ots].blockNumber == 0) {
+            emit Stamped(msg.sender, file_hash, ots);
+            hashstore[ots] = Dato({blockNumber: block.number, hash: file_hash});
+        }
     }
 
-    function verify(uint256 ots, uint256 file_hash) public view returns(bool){
+    function verify(string ots, string file_hash) public view returns(bool){
         Dato memory dato = hashstore[ots];
-        return dato.hash == file_hash;
+        return stringsEqual(dato.hash, file_hash);
     }
 
-    function getHash(uint256 ots) public view returns(uint256){
+    function getHash(string ots) public view returns(string){
         Dato memory dato = hashstore[ots];
         return dato.hash;
     }
 
-    function getBlockNumber(uint256 ots) public view returns(uint){
+    function getBlockNumber(string ots) public view returns(uint){
         Dato memory dato = hashstore[ots];
         return dato.blockNumber;
     }
+
+    function stringsEqual(string memory _a, string memory _b) internal pure returns (bool) {
+        bytes memory a = bytes(_a);
+        bytes memory b = bytes(_b);
+
+        if (keccak256(a) != keccak256(b)) { return false; }
+        return true;
+    }
+
+    function selfDestroy() public{
+        require(msg.sender == owner);
+        emit SelfDestroy(msg.sender);
+        selfdestruct(owner);
+    }
 }
\ No newline at end of file
diff --git a/SmartContracts/README.md b/SmartContracts/README.md
index c4aa6e79d69a40a9f8de9c10bfeef162806052e3..ba761b69d9841c8dbfc0996c286478712cab5c46 100644
--- a/SmartContracts/README.md
+++ b/SmartContracts/README.md
@@ -1 +1,20 @@
-Contracts de verify y stamp
+Contrato de prueba de existencia
+
+Este smart contract está desarrollado en solidity
+
+Interfaz:
+
+- Constructor: Define el poseedor del contrato como aquel que deploya el contrato, emite el evento Deploy
+
+- stamp(string clave, string valor) -> void : el contrato guarda valor y bloque en un diccionario para la clave dada, si la clave ya estaba asignada, no hace nada. Emite el evento Stamped, en el caso que sí se haga la asignación, con los parámetros indexados sobre la clave, el valor y la cuenta que envió la transacción
+
+- verify(string clave, string valor) -> bool : verifica que para la clave dada, tiene el valor asignado  en el diccionario
+
+- getBlock(string clave) -> unsigned int : precondición: está definido el diccionario, devuelve el int que corresponde al número de bloque donde se hizo el stamp original
+
+- selfDestroy() -> void : precondición: el usuario es el poseedor del contrato. Invoca el selfdestroy del contrato, y se envía todo el eter que tenga al poseedor del contrato, emite el evento SelfDestroy con esos parámetros
+
+
+Notas:
+
+- Se debería hacer un call del verify antes de hacer una transacción de stamp, para que en el caso de que ya exista, no consumir gas innecesario