#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
long long mod = 1000000007;
long long add(long long a, long long b, long long mod) {
  return (a % mod + b % mod) % mod;
}
long long sub(long long a, long long b, long long mod) {
  return (a % mod - b % mod + mod) % mod;
}
long long mul(long long a, long long b, long long mod) {
  return ((a % mod) * (b % mod)) % mod;
}
long long power(long long a, long long b, long long mod) {
  long long ans = 1;
  while (b > 0) {
    if (b % 2 == 1) ans = mul(ans, a, mod);
    a = mul(a, a, mod);
    b /= 2;
  }
  return ans;
}
int gcd, x, y;
void extendedEuclid(int A, int B) {
  if (B == 0) {
    gcd = A;
    x = 1;
    y = 0;
  } else {
    extendedEuclid(B, A % B);
    int temp = x;
    x = y;
    y = temp - (A / B) * y;
  }
}
long long modularInverse(long long A, long long M) {
  extendedEuclid(A, M);
  return (x % M + M) % M;
}
long long modularInversePrime(long long A, long long M) {
  return power(A, M - 2, M);
}
long long div(long long a, long long b, long long mod) {
  return ((a % mod) * (modularInverse(b, mod) % mod)) % mod;
}
vector<int> prefix_function(string s) {
  int n = s.length();
  vector<int> p(n);
  p[0] = 0;
  for (int i = 1; i < n; i++) {
    int j = p[i - 1];
    while (j > 0 && s[i] != s[j]) {
      j = p[j - 1];
    }
    if (s[i] == s[j]) {
      j++;
    }
    p[i] = j;
  }
  return p;
}
void reverse(string &s) { reverse(s.begin(), s.end()); }
struct node {
  int data;
  struct node *left;
  struct node *right;
};
struct node *newNode(int element) {
  struct node *temp = (node *)malloc(sizeof(node *));
  temp->data = element;
  temp->left = temp->right = NULL;
  return temp;
}
int maxDepth(struct node *v) {
  if (v == NULL) {
    return 0;
  } else {
    int ldepth = maxDepth(v->left);
    int rdepth = maxDepth(v->right);
    return max(ldepth, rdepth) + 1;
  }
}
void preorder(struct node *root, int q) {
  if (root) {
    printf("%d ", root->data);
    preorder(root->left, q);
    preorder(root->right, q);
  }
}
void postorder(struct node *root) {
  if (root) {
    postorder(root->left);
    postorder(root->right);
    printf("%d ", root->data);
  }
}
void inorder(struct node *root) {
  if (root) {
    inorder(root->left);
    printf("%d ", root->data);
    inorder(root->right);
  }
}
struct node *insert(struct node *root, int data) {
  if (root == NULL) {
    return newNode(data);
  } else {
    if (data <= root->data) {
      root->left = insert(root->left, data);
    } else {
      root->right = insert(root->right, data);
    }
  }
  return root;
}
struct node *lca(long long x, long long y, struct node *root) {
  if (root->data < x && root->data < y) {
    return lca(x, y, root->right);
  } else if (root->data > x && root->data > y) {
    return lca(x, y, root->left);
  }
  return root;
}
vector<pair<int, int> > pset(1000);
void initSet(int _size) {
  pset.resize(_size);
  for (int i = 0; i <= _size - 1; i++) pset[i] = {i, 1};
}
int findSet(int i) {
  return pset[i].first == i ? i : (pset[i].first = findSet(pset[i].first));
}
int sizeOfSet(int i) { return pset[findSet(i)].second; }
void unionSet(int i, int j) {
  if (sizeOfSet(i) < sizeOfSet(j)) swap(i, j);
  pset[findSet(i)].first = pset[findSet(j)].first;
}
bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
int numberOfSets() {
  int cnt = 0;
  for (int i = 0; i <= pset.size() - 1; i++)
    if (pset[i].first == i) cnt++;
  return cnt;
}
vector<int> segment_tree;
void init_segment_tree(int N) {
  int length = (int)(2 * pow(2.0, floor((log((double)N) / log(2.0)) + 1)));
  segment_tree.resize(length, 0);
}
void build_segment_tree(int code, int A[], int node, int b, int e) {
  if (b == e) {
    if (code == 0)
      segment_tree[node] = A[b];
    else
      segment_tree[node] = b;
  } else {
    int leftIdx = 2 * node, rightIdx = 2 * node + 1;
    build_segment_tree(code, A, leftIdx, b, (b + e) / 2);
    build_segment_tree(code, A, rightIdx, (b + e) / 2 + 1, e);
    int lContent = segment_tree[leftIdx], rContent = segment_tree[rightIdx];
    if (code == 0)
      segment_tree[node] = lContent + rContent;
    else {
      int lValue = A[lContent];
      int rValue = A[rContent];
      if (code == 1)
        segment_tree[node] = (lValue < rValue) ? lContent : rContent;
      else
        segment_tree[node] = (lValue > rValue) ? lContent : rContent;
    }
  }
}
int query(int code, int A[], int node, int b, int e, int i, int j) {
  if (i > e || j < b) return -1;
  if (b >= i && e <= j) return segment_tree[node];
  int p1 = query(code, A, 2 * node, b, (b + e) / 2, i, j);
  int p2 = query(code, A, 2 * node + 1, (b + e) / 2 + 1, e, i, j);
  if (p1 == -1) return p2;
  if (p2 == -1) return p1;
  if (code == 0)
    return p1 + p2;
  else if (code == 1)
    return (A[p1] < A[p2]) ? p1 : p2;
  else
    return (A[p1] > A[p2]) ? p1 : p2;
}
void update(int code, int A[], int pos, int new_val, int node, int b, int e) {
  if (b == e) {
    segment_tree[node] = new_val;
  } else {
    int mid = (b + e) / 2;
    if (pos <= mid) {
      update(code, A, pos, new_val, 2 * node, b, mid);
    } else
      update(code, A, pos, new_val, 2 * node + 1, mid + 1, e);
    int lContent = segment_tree[2 * node];
    int rContent = segment_tree[2 * node + 1];
    if (code == 0)
      segment_tree[node] = lContent + rContent;
    else if (code == 1)
      segment_tree[node] = (A[lContent] < A[rContent]) ? lContent : rContent;
    else
      segment_tree[node] = (A[lContent] > A[rContent]) ? lContent : rContent;
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n, m;
  cin >> n >> m;
  map<int, int> make_pair;
  vector<pair<int, int> > v;
  bool f = 0;
  int sum = 0;
  for (int i = 0; i <= m - 1; i++) {
    int a, b;
    cin >> a >> b;
    if (make_pair.count(a)) {
      if (make_pair[a] != b) {
        f = 1;
      }
    } else {
      make_pair[a] = b;
      sum += b;
    }
  }
  if (f == 1 || sum == 0) {
    cout << "-1";
  } else
    for (int i = 1; i <= n; i++) {
      cout << make_pair[i];
    }
  cout << "\n";
  return 0;
}
